From arigo at codespeak.net Fri Dec 1 03:44:42 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 1 Dec 2006 03:44:42 +0100 (CET) Subject: [pypy-svn] r35184 - in pypy/branch/jit-real-world/pypy: annotation config interpreter interpreter/test module/_pickle_support objspace/flow tool Message-ID: <20061201024442.5A66D1006E@code0.codespeak.net> Author: arigo Date: Fri Dec 1 03:43:34 2006 New Revision: 35184 Added: pypy/branch/jit-real-world/pypy/tool/pairtype.py - copied unchanged from r35175, pypy/branch/jit-real-world/pypy/annotation/pairtype.py Removed: pypy/branch/jit-real-world/pypy/interpreter/opcodeorder.py Modified: pypy/branch/jit-real-world/pypy/annotation/pairtype.py pypy/branch/jit-real-world/pypy/config/pypyoption.py pypy/branch/jit-real-world/pypy/interpreter/baseobjspace.py pypy/branch/jit-real-world/pypy/interpreter/eval.py pypy/branch/jit-real-world/pypy/interpreter/function.py pypy/branch/jit-real-world/pypy/interpreter/generator.py pypy/branch/jit-real-world/pypy/interpreter/nestedscope.py pypy/branch/jit-real-world/pypy/interpreter/pycode.py pypy/branch/jit-real-world/pypy/interpreter/pyframe.py pypy/branch/jit-real-world/pypy/interpreter/pyopcode.py pypy/branch/jit-real-world/pypy/interpreter/test/test_interpreter.py pypy/branch/jit-real-world/pypy/interpreter/test/test_pyframe.py pypy/branch/jit-real-world/pypy/interpreter/typedef.py pypy/branch/jit-real-world/pypy/module/_pickle_support/maker.py pypy/branch/jit-real-world/pypy/objspace/flow/flowcontext.py pypy/branch/jit-real-world/pypy/objspace/flow/framestate.py pypy/branch/jit-real-world/pypy/tool/stdlib_opcode.py Log: (pedronis, arigo) Intermediate check-in #2. More seriously, we rewrote the interpreter main loop in a style that should be easier for the JIT to grasp, but also -- possibly -- easier for human beings to grasp. A bit. Many levels of wrapping of stuff into other stuff are avoided now, and the PyFrame class hierarchy was completely removed. There is a possibly nice way to add opcodes from outside, with config options to enable them. The drawback is that the core main loop uses modern RPython magic. Translation not tested. It makes py.py slower by 30% but we hope that pypy-c will be faster. Modified: pypy/branch/jit-real-world/pypy/annotation/pairtype.py ============================================================================== --- pypy/branch/jit-real-world/pypy/annotation/pairtype.py (original) +++ pypy/branch/jit-real-world/pypy/annotation/pairtype.py Fri Dec 1 03:43:34 2006 @@ -1,63 +1,4 @@ -""" -Two magic tricks for classes: +# no longer there, sorry +# XXX fix all these imports - class X: - __metaclass__ = extendabletype - ... - - # in some other file... - class __extend__(X): - ... # and here you can add new methods and class attributes to X - -Mostly useful together with the second trick, which lets you build -methods whose 'self' is a pair of objects instead of just one: - - class __extend__(pairtype(X, Y)): - attribute = 42 - def method((x, y), other, arguments): - ... - - pair(x, y).attribute - pair(x, y).method(other, arguments) - -This finds methods and class attributes based on the actual -class of both objects that go into the pair(), with the usual -rules of method/attribute overriding in (pairs of) subclasses. - -For more information, see test_pairtype. -""" - -class extendabletype(type): - """A type with a syntax trick: 'class __extend__(t)' actually extends - the definition of 't' instead of creating a new subclass.""" - def __new__(cls, name, bases, dict): - if name == '__extend__': - for cls in bases: - for key, value in dict.items(): - if key == '__module__': - continue - # XXX do we need to provide something more for pickling? - setattr(cls, key, value) - return None - else: - return super(extendabletype, cls).__new__(cls, name, bases, dict) - - -def pair(a, b): - """Return a pair object.""" - tp = pairtype(a.__class__, b.__class__) - return tp((a, b)) # tp is a subclass of tuple - -pairtypecache = {} - -def pairtype(cls1, cls2): - """type(pair(a,b)) is pairtype(a.__class__, b.__class__).""" - try: - pair = pairtypecache[cls1, cls2] - except KeyError: - name = 'pairtype(%s, %s)' % (cls1.__name__, cls2.__name__) - bases1 = [pairtype(base1, cls2) for base1 in cls1.__bases__] - bases2 = [pairtype(cls1, base2) for base2 in cls2.__bases__] - bases = tuple(bases1 + bases2) or (tuple,) # 'tuple': ultimate base - pair = pairtypecache[cls1, cls2] = extendabletype(name, bases, {}) - return pair +from pypy.tool.pairtype import * Modified: pypy/branch/jit-real-world/pypy/config/pypyoption.py ============================================================================== --- pypy/branch/jit-real-world/pypy/config/pypyoption.py (original) +++ pypy/branch/jit-real-world/pypy/config/pypyoption.py Fri Dec 1 03:43:34 2006 @@ -37,6 +37,9 @@ ["cpython", "ast"], "ast", cmdline='--compiler'), + OptionDescription("opcodes", "opcodes to enable in the interpreter", [ + ]), + BoolOption("nofaking", "disallow faking in the object space", default=False, requires=[ Modified: pypy/branch/jit-real-world/pypy/interpreter/baseobjspace.py ============================================================================== --- pypy/branch/jit-real-world/pypy/interpreter/baseobjspace.py (original) +++ pypy/branch/jit-real-world/pypy/interpreter/baseobjspace.py Fri Dec 1 03:43:34 2006 @@ -174,6 +174,10 @@ from pypy.config.pypyoption import pypy_optiondescription config = Config(pypy_optiondescription) self.config = config + + # import extra modules for side-effects, possibly based on config + import pypy.interpreter.nestedscope # register *_DEREF bytecodes + self.interned_strings = {} self.pending_actions = [] self.setoptions(**kw) Modified: pypy/branch/jit-real-world/pypy/interpreter/eval.py ============================================================================== --- pypy/branch/jit-real-world/pypy/interpreter/eval.py (original) +++ pypy/branch/jit-real-world/pypy/interpreter/eval.py Fri Dec 1 03:43:34 2006 @@ -147,28 +147,3 @@ new_fastlocals_w[i] = w_value self.setfastscope(new_fastlocals_w) - - -class EvalFrame(Frame): - - def resume(self): - "Resume the execution of the frame from its current state." - executioncontext = self.space.getexecutioncontext() - executioncontext.enter(self) - try: - result = self.eval(executioncontext) - rstack.resume_point("evalframe", self, executioncontext, returns=result) - finally: - executioncontext.leave(self) - return result - - # running a frame is usually the same as resuming it from its - # initial state, but not for generator frames - run = resume - - def eval(self, executioncontext): - "Abstract method to override." - raise TypeError, "abstract" - - def hide(self): - return False Modified: pypy/branch/jit-real-world/pypy/interpreter/function.py ============================================================================== --- pypy/branch/jit-real-world/pypy/interpreter/function.py (original) +++ pypy/branch/jit-real-world/pypy/interpreter/function.py Fri Dec 1 03:43:34 2006 @@ -9,7 +9,6 @@ from pypy.interpreter.error import OperationError from pypy.interpreter.baseobjspace import Wrappable from pypy.interpreter.eval import Code -from pypy.interpreter.pyframe import PyFrame from pypy.interpreter.argument import Arguments, ArgumentsFromValuestack class Function(Wrappable): Modified: pypy/branch/jit-real-world/pypy/interpreter/generator.py ============================================================================== --- pypy/branch/jit-real-world/pypy/interpreter/generator.py (original) +++ pypy/branch/jit-real-world/pypy/interpreter/generator.py Fri Dec 1 03:43:34 2006 @@ -1,38 +1,5 @@ from pypy.interpreter.error import OperationError from pypy.interpreter.baseobjspace import Wrappable -from pypy.interpreter.eval import EvalFrame -from pypy.interpreter.pyframe import ControlFlowException, ExitFrame - -# -# Generator support. Note that GeneratorFrame is not a subclass of PyFrame. -# PyCode objects use a custom subclass of both PyFrame and GeneratorFrame -# when they need to interpret Python bytecode that is a generator. -# Otherwise, GeneratorFrame could also be used to define, say, -# built-in generators (which are usually done in CPython as functions -# that return iterators). -# - -class GeneratorFrameMixin(object): - "A frame attached to a generator." - _mixin_ = True - - def run(self): - "Build a generator-iterator." - return self.space.wrap(GeneratorIterator(self)) - - ### extra opcodes ### - - # XXX mmmh, GeneratorFrame is supposed to be independent from - # Python bytecode... Well, it is. These are not used when - # GeneratorFrame is used with other kinds of Code subclasses. - - def RETURN_VALUE(f): # overridden - raise SGeneratorReturn() - - def YIELD_VALUE(f): - w_yieldedvalue = f.valuestack.pop() - raise SYieldValue(w_yieldedvalue) - YIELD_STMT = YIELD_VALUE # misnamed in old versions of dis.opname class GeneratorIterator(Wrappable): @@ -42,7 +9,6 @@ self.space = frame.space self.frame = frame self.running = False - self.exhausted = False def descr__reduce__(self, space): from pypy.interpreter.mixedmodule import MixedModule @@ -54,7 +20,6 @@ tup = [ w(self.frame), w(self.running), - w(self.exhausted), ] return space.newtuple([new_inst, space.newtuple(tup)]) @@ -69,34 +34,21 @@ if self.running: raise OperationError(space.w_ValueError, space.wrap('generator already executing')) - if self.exhausted: + if self.frame.frame_finished_execution: raise OperationError(space.w_StopIteration, space.w_None) self.running = True try: try: - return self.frame.resume() + w_result = self.frame.execute_frame() except OperationError: - self.exhausted = True + # errors finish a frame + self.frame.frame_finished_execution = True raise + # if the frame is now marked as finished, it was RETURNed from + if self.frame.frame_finished_execution: + raise OperationError(space.w_StopIteration, space.w_None) + else: + return w_result # YIELDed finally: self.frame.f_back = None self.running = False - -# -# the specific ControlFlowExceptions used by generators -# - -class SYieldValue(ControlFlowException): - """Signals a 'yield' statement. - Argument is the wrapped object to return.""" - - def __init__(self, w_yieldvalue): - self.w_yieldvalue = w_yieldvalue - - def action(self, frame): - raise ExitFrame(self.w_yieldvalue) - -class SGeneratorReturn(ControlFlowException): - """Signals a 'return' statement inside a generator.""" - def emptystack(self, frame): - raise OperationError(frame.space.w_StopIteration, frame.space.w_None) Modified: pypy/branch/jit-real-world/pypy/interpreter/nestedscope.py ============================================================================== --- pypy/branch/jit-real-world/pypy/interpreter/nestedscope.py (original) +++ pypy/branch/jit-real-world/pypy/interpreter/nestedscope.py Fri Dec 1 03:43:34 2006 @@ -1,5 +1,4 @@ from pypy.interpreter.error import OperationError -from pypy.interpreter.pyopcode import PyInterpFrame from pypy.interpreter import function, pycode, pyframe from pypy.interpreter.baseobjspace import Wrappable from pypy.interpreter.mixedmodule import MixedModule @@ -59,7 +58,12 @@ content, uid(self)) -class PyNestedScopeFrame(PyInterpFrame): +super_initialize_frame_scopes = pyframe.PyFrame.initialize_frame_scopes +super_fast2locals = pyframe.PyFrame.fast2locals +super_locals2fast = pyframe.PyFrame.locals2fast + + +class __extend__(pyframe.PyFrame): """This class enhances a standard frame with nested scope abilities, i.e. handling of cell/free variables.""" @@ -69,28 +73,47 @@ # variables coming from a parent function in which i'm nested # 'closure' is a list of Cell instances: the received free vars. - def __init__(self, space, code, w_globals, closure): - PyInterpFrame.__init__(self, space, code, w_globals, closure) + cells = None + + def initialize_frame_scopes(self, closure): + super_initialize_frame_scopes(self, closure) + code = self.pycode ncellvars = len(code.co_cellvars) nfreevars = len(code.co_freevars) - if closure is None: - if nfreevars: - raise OperationError(space.w_TypeError, - space.wrap("directly executed code object " - "may not contain free variables")) - closure = [] - else: - if len(closure) != nfreevars: - raise ValueError("code object received a closure with " + if not nfreevars: + if not ncellvars: + return # no self.cells needed - fast path + if closure is None: + closure = [] + elif closure is None: + space = self.space + raise OperationError(space.w_TypeError, + space.wrap("directly executed code object " + "may not contain free variables")) + if len(closure) != nfreevars: + raise ValueError("code object received a closure with " "an unexpected number of free variables") self.cells = [Cell() for i in range(ncellvars)] + closure def getclosure(self): + if self.cells is None: + return None ncellvars = len(self.pycode.co_cellvars) # not part of the closure return self.cells[ncellvars:] + def _getcells(self): + return self.cells + + def _setcellvars(self, cellvars): + ncellvars = len(self.pycode.co_cellvars) + if len(cellvars) != ncellvars: + raise OperationError(self.space.w_TypeError, + self.space.wrap("bad cellvars")) + if self.cells is not None: + self.cells[:ncellvars] = cellvars + def fast2locals(self): - PyInterpFrame.fast2locals(self) + super_fast2locals(self) # cellvars are values exported to inner scopes # freevars are values coming from outer scopes freevarnames = self.pycode.co_cellvars + self.pycode.co_freevars @@ -106,7 +129,7 @@ self.space.setitem(self.w_locals, w_name, w_value) def locals2fast(self): - PyInterpFrame.locals2fast(self) + super_locals2fast(self) freevarnames = self.pycode.co_cellvars + self.pycode.co_freevars for i in range(len(freevarnames)): name = freevarnames[i] @@ -121,6 +144,8 @@ cell.set(w_value) def init_cells(self): + if self.cells is None: + return args_to_copy = self.pycode._args_as_cellvars for i in range(len(args_to_copy)): argnum = args_to_copy[i] @@ -136,13 +161,13 @@ ### extra opcodes ### - def LOAD_CLOSURE(f, varindex): + def LOAD_CLOSURE(f, varindex, *ignored): # nested scopes: access the cell object cell = f.cells[varindex] w_value = f.space.wrap(cell) f.valuestack.push(w_value) - def LOAD_DEREF(f, varindex): + def LOAD_DEREF(f, varindex, *ignored): # nested scopes: access a variable through its cell object cell = f.cells[varindex] try: @@ -160,7 +185,7 @@ else: f.valuestack.push(w_value) - def STORE_DEREF(f, varindex): + def STORE_DEREF(f, varindex, *ignored): # nested scopes: access a variable through its cell object w_newvalue = f.valuestack.pop() #try: @@ -170,7 +195,7 @@ # raise cell.set(w_newvalue) - def MAKE_CLOSURE(f, numdefaults): + def MAKE_CLOSURE(f, numdefaults, *ignored): w_codeobj = f.valuestack.pop() codeobj = f.space.interp_w(pycode.PyCode, w_codeobj) if codeobj.magic >= 0xa0df281: # CPython 2.5 AST branch merge Modified: pypy/branch/jit-real-world/pypy/interpreter/pycode.py ============================================================================== --- pypy/branch/jit-real-world/pypy/interpreter/pycode.py (original) +++ pypy/branch/jit-real-world/pypy/interpreter/pycode.py Fri Dec 1 03:43:34 2006 @@ -9,7 +9,7 @@ from pypy.interpreter import eval from pypy.interpreter.error import OperationError from pypy.interpreter.gateway import NoneNotWrapped -from pypy.interpreter.baseobjspace import ObjSpace, W_Root +from pypy.interpreter.baseobjspace import ObjSpace, W_Root from pypy.rlib.rarithmetic import intmask # helper @@ -49,29 +49,6 @@ cpython_magic, = struct.unpack("= pythonopcode.HAVE_ARGUMENT: - oparg = self.nextarg() - while True: - if opcode == pythonopcode.EXTENDED_ARG: - opcode = self.nextop() - oparg = oparg<<16 | self.nextarg() - if opcode < pythonopcode.HAVE_ARGUMENT: - raise pyframe.BytecodeCorruption - continue - else: - fn = self.dispatch_table_w_arg[opcode] - fn(self, oparg) - break + # For the sequel, force 'next_instr' to be unsigned for performance + next_instr = r_uint(self.last_instr) + opcode = ord(co_code[next_instr]) + next_instr += 1 + if space.config.objspace.logbytecodes: + space.bytecodecounts[opcode] = space.bytecodecounts.get(opcode, 0) + 1 + + if opcode >= HAVE_ARGUMENT: + lo = ord(co_code[next_instr]) + hi = ord(co_code[next_instr+1]) + next_instr += 2 + oparg = (hi << 8) | lo else: - fn = self.dispatch_table_no_arg[opcode] - fn(self) + oparg = 0 - def nextop(self): - c = self.pycode.co_code[self.next_instr] - self.next_instr += 1 - return ord(c) - - def nextarg(self): - lo = self.nextop() - hi = self.nextop() - return (hi<<8) + lo + while opcode == opcodedesc.EXTENDED_ARG.index: + opcode = ord(co_code[next_instr]) + if opcode < HAVE_ARGUMENT: + raise BytecodeCorruption + lo = ord(co_code[next_instr+1]) + hi = ord(co_code[next_instr+2]) + next_instr += 3 + oparg = (oparg << 16) | (hi << 8) | lo + + if opcode == opcodedesc.RETURN_VALUE.index: + w_returnvalue = self.valuestack.pop() + block = self.unrollstack(SReturnValue.kind) + if block is None: + self.frame_finished_execution = True # for generators + return w_returnvalue + else: + unroller = SReturnValue(w_returnvalue) + next_instr = block.handle(self, unroller) + continue # now inside a 'finally' block + + if opcode == opcodedesc.YIELD_VALUE.index: + w_yieldvalue = self.valuestack.pop() + return w_yieldvalue + + if opcode == opcodedesc.END_FINALLY.index: + # unlike CPython, when we reach this opcode the value stack has + # always been set up as follows (topmost first): + # [exception type or None] + # [exception value or None] + # [wrapped stack unroller ] + self.valuestack.pop() # ignore the exception type + self.valuestack.pop() # ignore the exception value + w_unroller = self.valuestack.pop() + unroller = self.space.interpclass_w(w_unroller) + if isinstance(unroller, SuspendedUnroller): + # go on unrolling the stack + block = self.unrollstack(unroller.kind) + if block is None: + self.frame_finished_execution = True # for generators + return unroller.nomoreblocks() + else: + next_instr = block.handle(self, unroller) + continue + + if we_are_translated(): + for opdesc in unrolling_opcode_descs: + # static checks to skip this whole case if necessary + if not opdesc.is_enabled(space): + continue + if not hasattr(pyframe.PyFrame, opdesc.methodname): + continue # e.g. for JUMP_FORWARD, implemented above + + if opcode == opdesc.index: + # dispatch to the opcode method + meth = getattr(self, opdesc.methodname) + res = meth(oparg, next_instr) + # !! warning, for the annotator the next line is not + # comparing an int and None - you can't do that. + # Instead, it's constant-folded to either True or False + if res is not None: + next_instr = res + break + else: + self.MISSING_OPCODE(oparg, next_instr) + + else: # when we are not translated, a list lookup is much faster + methodname = opcode_method_names[opcode] + res = getattr(self, methodname)(oparg, next_instr) + if res is not None: + next_instr = res + + def unrollstack(self, unroller_kind): + while not self.blockstack.empty(): + block = self.blockstack.pop() + if (block.handling_mask & unroller_kind) != 0: + return block + return None + + def unrollstack_and_jump(self, unroller): + block = self.unrollstack(unroller.kind) + if block is None: + raise BytecodeCorruption("misplaced bytecode - should not return") + return block.handle(self, unroller) ### accessor functions ### @@ -110,10 +225,10 @@ # the 'self' argument of opcode implementations is called 'f' # for historical reasons - def NOP(f): + def NOP(f, *ignored): pass - def LOAD_FAST(f, varindex): + def LOAD_FAST(f, varindex, *ignored): # access a local variable directly w_value = f.fastlocals_w[varindex] if w_value is None: @@ -122,11 +237,11 @@ raise OperationError(f.space.w_UnboundLocalError, f.space.wrap(message)) f.valuestack.push(w_value) - def LOAD_CONST(f, constindex): + def LOAD_CONST(f, constindex, *ignored): w_const = f.getconstant_w(constindex) f.valuestack.push(w_const) - def STORE_FAST(f, varindex): + def STORE_FAST(f, varindex, *ignored): w_newvalue = f.valuestack.pop() f.fastlocals_w[varindex] = w_newvalue #except: @@ -139,16 +254,16 @@ # print "co_nlocals", f.pycode.co_nlocals # raise - def POP_TOP(f): + def POP_TOP(f, *ignored): f.valuestack.pop() - def ROT_TWO(f): + def ROT_TWO(f, *ignored): w_1 = f.valuestack.pop() w_2 = f.valuestack.pop() f.valuestack.push(w_1) f.valuestack.push(w_2) - def ROT_THREE(f): + def ROT_THREE(f, *ignored): w_1 = f.valuestack.pop() w_2 = f.valuestack.pop() w_3 = f.valuestack.pop() @@ -156,7 +271,7 @@ f.valuestack.push(w_3) f.valuestack.push(w_2) - def ROT_FOUR(f): + def ROT_FOUR(f, *ignored): w_1 = f.valuestack.pop() w_2 = f.valuestack.pop() w_3 = f.valuestack.pop() @@ -166,11 +281,11 @@ f.valuestack.push(w_3) f.valuestack.push(w_2) - def DUP_TOP(f): + def DUP_TOP(f, *ignored): w_1 = f.valuestack.top() f.valuestack.push(w_1) - def DUP_TOPX(f, itemcount): + def DUP_TOPX(f, itemcount, *ignored): assert 1 <= itemcount <= 5, "limitation of the current interpreter" for i in range(itemcount): w_1 = f.valuestack.top(itemcount-1) @@ -182,7 +297,7 @@ UNARY_CONVERT = unaryoperation("repr") UNARY_INVERT = unaryoperation("invert") - def BINARY_POWER(f): + def BINARY_POWER(f, *ignored): w_2 = f.valuestack.pop() w_1 = f.valuestack.pop() w_result = f.space.pow(w_1, w_2, f.space.w_None) @@ -203,7 +318,7 @@ BINARY_XOR = binaryoperation("xor") BINARY_OR = binaryoperation("or_") - def INPLACE_POWER(f): + def INPLACE_POWER(f, *ignored): w_2 = f.valuestack.pop() w_1 = f.valuestack.pop() w_result = f.space.inplace_pow(w_1, w_2) @@ -228,18 +343,18 @@ w_result = f.space.getslice(w_obj, w_start, w_end) f.valuestack.push(w_result) - def SLICE_0(f): + def SLICE_0(f, *ignored): f.slice(f.space.w_None, f.space.w_None) - def SLICE_1(f): + def SLICE_1(f, *ignored): w_start = f.valuestack.pop() f.slice(w_start, f.space.w_None) - def SLICE_2(f): + def SLICE_2(f, *ignored): w_end = f.valuestack.pop() f.slice(f.space.w_None, w_end) - def SLICE_3(f): + def SLICE_3(f, *ignored): w_end = f.valuestack.pop() w_start = f.valuestack.pop() f.slice(w_start, w_end) @@ -249,18 +364,18 @@ w_newvalue = f.valuestack.pop() f.space.setslice(w_obj, w_start, w_end, w_newvalue) - def STORE_SLICE_0(f): + def STORE_SLICE_0(f, *ignored): f.storeslice(f.space.w_None, f.space.w_None) - def STORE_SLICE_1(f): + def STORE_SLICE_1(f, *ignored): w_start = f.valuestack.pop() f.storeslice(w_start, f.space.w_None) - def STORE_SLICE_2(f): + def STORE_SLICE_2(f, *ignored): w_end = f.valuestack.pop() f.storeslice(f.space.w_None, w_end) - def STORE_SLICE_3(f): + def STORE_SLICE_3(f, *ignored): w_end = f.valuestack.pop() w_start = f.valuestack.pop() f.storeslice(w_start, w_end) @@ -269,69 +384,69 @@ w_obj = f.valuestack.pop() f.space.delslice(w_obj, w_start, w_end) - def DELETE_SLICE_0(f): + def DELETE_SLICE_0(f, *ignored): f.deleteslice(f.space.w_None, f.space.w_None) - def DELETE_SLICE_1(f): + def DELETE_SLICE_1(f, *ignored): w_start = f.valuestack.pop() f.deleteslice(w_start, f.space.w_None) - def DELETE_SLICE_2(f): + def DELETE_SLICE_2(f, *ignored): w_end = f.valuestack.pop() f.deleteslice(f.space.w_None, w_end) - def DELETE_SLICE_3(f): + def DELETE_SLICE_3(f, *ignored): w_end = f.valuestack.pop() w_start = f.valuestack.pop() f.deleteslice(w_start, w_end) - def STORE_SUBSCR(f): + def STORE_SUBSCR(f, *ignored): "obj[subscr] = newvalue" w_subscr = f.valuestack.pop() w_obj = f.valuestack.pop() w_newvalue = f.valuestack.pop() f.space.setitem(w_obj, w_subscr, w_newvalue) - def DELETE_SUBSCR(f): + def DELETE_SUBSCR(f, *ignored): "del obj[subscr]" w_subscr = f.valuestack.pop() w_obj = f.valuestack.pop() f.space.delitem(w_obj, w_subscr) - def PRINT_EXPR(f): + def PRINT_EXPR(f, *ignored): w_expr = f.valuestack.pop() print_expr(f.space, w_expr) - def PRINT_ITEM_TO(f): + def PRINT_ITEM_TO(f, *ignored): w_stream = f.valuestack.pop() w_item = f.valuestack.pop() if f.space.is_w(w_stream, f.space.w_None): w_stream = sys_stdout(f.space) # grumble grumble special cases print_item_to(f.space, w_item, w_stream) - def PRINT_ITEM(f): + def PRINT_ITEM(f, *ignored): w_item = f.valuestack.pop() print_item(f.space, w_item) - def PRINT_NEWLINE_TO(f): + def PRINT_NEWLINE_TO(f, *ignored): w_stream = f.valuestack.pop() if f.space.is_w(w_stream, f.space.w_None): w_stream = sys_stdout(f.space) # grumble grumble special cases print_newline_to(f.space, w_stream) - def PRINT_NEWLINE(f): + def PRINT_NEWLINE(f, *ignored): print_newline(f.space) - def BREAK_LOOP(f): - raise pyframe.SBreakLoop - - def CONTINUE_LOOP(f, startofloop): - raise pyframe.SContinueLoop(startofloop) + def BREAK_LOOP(f, *ignored): + next_instr = f.unrollstack_and_jump(SBreakLoop.singleton) + return next_instr + + def CONTINUE_LOOP(f, startofloop, *ignored): + unroller = SContinueLoop(startofloop) + next_instr = f.unrollstack_and_jump(unroller) + return next_instr - def RAISE_VARARGS(f, nbargs): - # we use the .app.py file to prepare the exception/value/traceback - # but not to actually raise it, because we cannot use the 'raise' - # statement to implement RAISE_VARARGS + def RAISE_VARARGS(f, nbargs, *ignored): space = f.space if nbargs == 0: operror = space.getexecutioncontext().sys_exc_info() @@ -339,7 +454,9 @@ raise OperationError(space.w_TypeError, space.wrap("raise: no active exception to re-raise")) # re-raise, no new traceback obj will be attached - raise pyframe.SApplicationException(operror) + f.last_exception = operror + raise Reraise + w_value = w_traceback = space.w_None if nbargs >= 3: w_traceback = f.valuestack.pop() if nbargs >= 2: w_value = f.valuestack.pop() @@ -357,16 +474,13 @@ space.wrap("raise: arg 3 must be a traceback or None")) operror.application_traceback = tb # re-raise, no new traceback obj will be attached - raise pyframe.SApplicationException(operror) + f.last_exception = operror + raise Reraise - def LOAD_LOCALS(f): + def LOAD_LOCALS(f, *ignored): f.valuestack.push(f.w_locals) - def RETURN_VALUE(f): - w_returnvalue = f.valuestack.pop() - raise pyframe.SReturnValue(w_returnvalue) - - def EXEC_STMT(f): + def EXEC_STMT(f, *ignored): w_locals = f.valuestack.pop() w_globals = f.valuestack.pop() w_prog = f.valuestack.pop() @@ -386,25 +500,11 @@ if plain: f.setdictscope(w_locals) - def POP_BLOCK(f): + def POP_BLOCK(f, *ignored): block = f.blockstack.pop() block.cleanup(f) # the block knows how to clean up the value stack - def END_FINALLY(f): - # unlike CPython, when we reach this opcode the value stack has - # always been set up as follows (topmost first): - # [exception type or None] - # [exception value or None] - # [wrapped stack unroller ] - f.valuestack.pop() # ignore the exception type - f.valuestack.pop() # ignore the exception value - w_unroller = f.valuestack.pop() - unroller = f.space.interpclass_w(w_unroller) - if isinstance(unroller, pyframe.SuspendedUnroller): - # re-raise the unroller, if any - raise unroller.flowexc - - def BUILD_CLASS(f): + def BUILD_CLASS(f, *ignored): w_methodsdict = f.valuestack.pop() w_bases = f.valuestack.pop() w_name = f.valuestack.pop() @@ -415,12 +515,12 @@ w_bases, w_methodsdict) f.valuestack.push(w_newclass) - def STORE_NAME(f, varindex): + def STORE_NAME(f, varindex, *ignored): w_varname = f.getname_w(varindex) w_newvalue = f.valuestack.pop() f.space.set_str_keyed_item(f.w_locals, w_varname, w_newvalue) - def DELETE_NAME(f, varindex): + def DELETE_NAME(f, varindex, *ignored): w_varname = f.getname_w(varindex) try: f.space.delitem(f.w_locals, w_varname) @@ -431,7 +531,7 @@ message = "name '%s' is not defined" % f.space.str_w(w_varname) raise OperationError(f.space.w_NameError, f.space.wrap(message)) - def UNPACK_SEQUENCE(f, itemcount): + def UNPACK_SEQUENCE(f, itemcount, *ignored): w_iterable = f.valuestack.pop() try: items = f.space.unpackiterable(w_iterable, itemcount) @@ -441,29 +541,29 @@ for item in items: f.valuestack.push(item) - def STORE_ATTR(f, nameindex): + def STORE_ATTR(f, nameindex, *ignored): "obj.attributename = newvalue" w_attributename = f.getname_w(nameindex) w_obj = f.valuestack.pop() w_newvalue = f.valuestack.pop() f.space.setattr(w_obj, w_attributename, w_newvalue) - def DELETE_ATTR(f, nameindex): + def DELETE_ATTR(f, nameindex, *ignored): "del obj.attributename" w_attributename = f.getname_w(nameindex) w_obj = f.valuestack.pop() f.space.delattr(w_obj, w_attributename) - def STORE_GLOBAL(f, nameindex): + def STORE_GLOBAL(f, nameindex, *ignored): w_varname = f.getname_w(nameindex) w_newvalue = f.valuestack.pop() f.space.set_str_keyed_item(f.w_globals, w_varname, w_newvalue) - def DELETE_GLOBAL(f, nameindex): + def DELETE_GLOBAL(f, nameindex, *ignored): w_varname = f.getname_w(nameindex) f.space.delitem(f.w_globals, w_varname) - def LOAD_NAME(f, nameindex): + def LOAD_NAME(f, nameindex, *ignored): if f.w_locals is not f.w_globals: w_varname = f.getname_w(nameindex) w_value = f.space.finditem(f.w_locals, w_varname) @@ -472,7 +572,7 @@ return f.LOAD_GLOBAL(nameindex) # fall-back - def LOAD_GLOBAL(f, nameindex): + def LOAD_GLOBAL(f, nameindex, *ignored): w_varname = f.getname_w(nameindex) w_value = f.space.finditem(f.w_globals, w_varname) if w_value is None: @@ -485,7 +585,7 @@ f.space.wrap(message)) f.valuestack.push(w_value) - def DELETE_FAST(f, varindex): + def DELETE_FAST(f, varindex, *ignored): if f.fastlocals_w[varindex] is None: varname = f.getlocalvarname(varindex) message = "local variable '%s' referenced before assignment" % varname @@ -493,25 +593,25 @@ f.fastlocals_w[varindex] = None - def BUILD_TUPLE(f, itemcount): + def BUILD_TUPLE(f, itemcount, *ignored): items = [f.valuestack.pop() for i in range(itemcount)] items.reverse() w_tuple = f.space.newtuple(items) f.valuestack.push(w_tuple) - def BUILD_LIST(f, itemcount): + def BUILD_LIST(f, itemcount, *ignored): items = [f.valuestack.pop() for i in range(itemcount)] items.reverse() w_list = f.space.newlist(items) f.valuestack.push(w_list) - def BUILD_MAP(f, zero): + def BUILD_MAP(f, zero, *ignored): if zero != 0: - raise pyframe.BytecodeCorruption + raise BytecodeCorruption w_dict = f.space.newdict() f.valuestack.push(w_dict) - def LOAD_ATTR(f, nameindex): + def LOAD_ATTR(f, nameindex, *ignored): "obj.attributename" w_attributename = f.getname_w(nameindex) w_obj = f.valuestack.pop() @@ -549,17 +649,17 @@ cmp_is_not, cmp_exc_match, ] - def COMPARE_OP(f, testnum): + def COMPARE_OP(f, testnum, *ignored): w_2 = f.valuestack.pop() w_1 = f.valuestack.pop() try: testfn = f.compare_dispatch_table[testnum] except IndexError: - raise pyframe.BytecodeCorruption, "bad COMPARE_OP oparg" + raise BytecodeCorruption, "bad COMPARE_OP oparg" w_result = testfn(f, w_1, w_2) f.valuestack.push(w_result) - def IMPORT_NAME(f, nameindex): + def IMPORT_NAME(f, nameindex, *ignored): space = f.space w_modulename = f.getname_w(nameindex) modulename = f.space.str_w(w_modulename) @@ -575,13 +675,13 @@ f.w_globals, w_locals, w_fromlist) f.valuestack.push(w_obj) - def IMPORT_STAR(f): + def IMPORT_STAR(f, *ignored): w_module = f.valuestack.pop() w_locals = f.getdictscope() import_all_from(f.space, w_module, w_locals) f.setdictscope(w_locals) - def IMPORT_FROM(f, nameindex): + def IMPORT_FROM(f, nameindex, *ignored): w_name = f.getname_w(nameindex) w_module = f.valuestack.top() try: @@ -593,29 +693,31 @@ f.space.wrap("cannot import name '%s'" % f.space.str_w(w_name) )) f.valuestack.push(w_obj) - def JUMP_FORWARD(f, stepby): - f.next_instr += stepby - JUMP_FORWARD.can_jump = True + def JUMP_FORWARD(f, jumpby, next_instr, *ignored): + next_instr += jumpby + return next_instr - def JUMP_IF_FALSE(f, stepby): + def JUMP_IF_FALSE(f, stepby, next_instr, *ignored): w_cond = f.valuestack.top() if not f.space.is_true(w_cond): - f.next_instr += stepby + next_instr += stepby + return next_instr - def JUMP_IF_TRUE(f, stepby): + def JUMP_IF_TRUE(f, stepby, next_instr, *ignored): w_cond = f.valuestack.top() if f.space.is_true(w_cond): - f.next_instr += stepby + next_instr += stepby + return next_instr - def JUMP_ABSOLUTE(f, jumpto): - f.next_instr = jumpto + def JUMP_ABSOLUTE(f, jumpto, next_instr, *ignored): + return jumpto - def GET_ITER(f): + def GET_ITER(f, *ignored): w_iterable = f.valuestack.pop() w_iterator = f.space.iter(w_iterable) f.valuestack.push(w_iterator) - def FOR_ITER(f, jumpby): + def FOR_ITER(f, jumpby, next_instr, *ignored): w_iterator = f.valuestack.top() try: w_nextitem = f.space.next(w_iterator) @@ -624,33 +726,33 @@ raise # iterator exhausted f.valuestack.pop() - f.next_instr += jumpby + next_instr += jumpby else: f.valuestack.push(w_nextitem) + return next_instr - def FOR_LOOP(f, oparg): - raise pyframe.BytecodeCorruption, "old opcode, no longer in use" + def FOR_LOOP(f, oparg, *ignored): + raise BytecodeCorruption, "old opcode, no longer in use" - def SETUP_LOOP(f, offsettoend): - block = pyframe.LoopBlock(f, f.next_instr + offsettoend) + def SETUP_LOOP(f, offsettoend, next_instr, *ignored): + block = LoopBlock(f, next_instr + offsettoend) f.blockstack.push(block) - def SETUP_EXCEPT(f, offsettoend): - block = pyframe.ExceptBlock(f, f.next_instr + offsettoend) + def SETUP_EXCEPT(f, offsettoend, next_instr, *ignored): + block = ExceptBlock(f, next_instr + offsettoend) f.blockstack.push(block) - def SETUP_FINALLY(f, offsettoend): - block = pyframe.FinallyBlock(f, f.next_instr + offsettoend) + def SETUP_FINALLY(f, offsettoend, next_instr, *ignored): + block = FinallyBlock(f, next_instr + offsettoend) f.blockstack.push(block) - def WITH_CLEANUP(f): + def WITH_CLEANUP(f, *ignored): # see comment in END_FINALLY for stack state w_exitfunc = f.valuestack.pop() w_unroller = f.valuestack.top(2) unroller = f.space.interpclass_w(w_unroller) - if (isinstance(unroller, pyframe.SuspendedUnroller) - and isinstance(unroller.flowexc, pyframe.SApplicationException)): - operr = unroller.flowexc.operr + if isinstance(unroller, SApplicationException): + operr = unroller.operr w_result = f.space.call_function(w_exitfunc, operr.w_type, operr.w_value, @@ -684,7 +786,7 @@ rstack.resume_point("call_function", f, returns=w_result) f.valuestack.push(w_result) - def CALL_FUNCTION(f, oparg): + def CALL_FUNCTION(f, oparg, *ignored): # XXX start of hack for performance if (oparg >> 8) & 0xff == 0: # Only positional arguments @@ -701,20 +803,20 @@ # general case f.call_function(oparg) - def CALL_FUNCTION_VAR(f, oparg): + def CALL_FUNCTION_VAR(f, oparg, *ignored): w_varargs = f.valuestack.pop() f.call_function(oparg, w_varargs) - def CALL_FUNCTION_KW(f, oparg): + def CALL_FUNCTION_KW(f, oparg, *ignored): w_varkw = f.valuestack.pop() f.call_function(oparg, None, w_varkw) - def CALL_FUNCTION_VAR_KW(f, oparg): + def CALL_FUNCTION_VAR_KW(f, oparg, *ignored): w_varkw = f.valuestack.pop() w_varargs = f.valuestack.pop() f.call_function(oparg, w_varargs, w_varkw) - def MAKE_FUNCTION(f, numdefaults): + def MAKE_FUNCTION(f, numdefaults, *ignored): w_codeobj = f.valuestack.pop() codeobj = f.space.interp_w(PyCode, w_codeobj) defaultarguments = [f.valuestack.pop() for i in range(numdefaults)] @@ -722,169 +824,244 @@ fn = function.Function(f.space, codeobj, f.w_globals, defaultarguments) f.valuestack.push(f.space.wrap(fn)) - def BUILD_SLICE(f, numargs): + def BUILD_SLICE(f, numargs, *ignored): if numargs == 3: w_step = f.valuestack.pop() elif numargs == 2: w_step = f.space.w_None else: - raise pyframe.BytecodeCorruption + raise BytecodeCorruption w_end = f.valuestack.pop() w_start = f.valuestack.pop() w_slice = f.space.newslice(w_start, w_end, w_step) f.valuestack.push(w_slice) - def LIST_APPEND(f): + def LIST_APPEND(f, *ignored): w = f.valuestack.pop() v = f.valuestack.pop() f.space.call_method(v, 'append', w) - def SET_LINENO(f, lineno): + def SET_LINENO(f, lineno, *ignored): pass -## def EXTENDED_ARG(f, oparg): +## def EXTENDED_ARG(f, oparg, *ignored): ## opcode = f.nextop() ## oparg = oparg<<16 | f.nextarg() ## fn = f.dispatch_table_w_arg[opcode] ## if fn is None: -## raise pyframe.BytecodeCorruption +## raise BytecodeCorruption ## fn(f, oparg) - def MISSING_OPCODE(f): - ofs = f.next_instr - 1 + def MISSING_OPCODE(f, oparg, next_instr, *ignored): + ofs = next_instr - 1 c = f.pycode.co_code[ofs] name = f.pycode.co_name - raise pyframe.BytecodeCorruption("unknown opcode, ofs=%d, code=%d, name=%s" % - (ofs, ord(c), name) ) - - def MISSING_OPCODE_W_ARG(f, oparg): - ofs = f.next_instr - 3 - c = f.pycode.co_code[ofs] - name = f.pycode.co_name - raise pyframe.BytecodeCorruption("unknown opcode, ofs=%d, code=%d, name=%s" % - (ofs, ord(c), name) ) + raise BytecodeCorruption("unknown opcode, ofs=%d, code=%d, name=%s" % + (ofs, ord(c), name) ) STOP_CODE = MISSING_OPCODE - ### dispatch_table ### - - # 'opcode_has_arg' is a class attribute: list of True/False whether opcode takes arg - # 'dispatch_table_no_arg: list of functions/None - # 'dispatch_table_w_arg: list of functions/None - - __metaclass__ = InitializedClass - def __initclass__(cls): - "NOT_RPYTHON" - # create the 'cls.dispatch_table' attribute - opcode_has_arg = [] - dispatch_table_no_arg = [] - dispatch_table_w_arg = [] - missing_opcode = cls.MISSING_OPCODE.im_func - missing_opcode_w_arg = cls.MISSING_OPCODE_W_ARG.im_func - for i in range(256): - opname = pythonopcode.opname[i].replace('+', '_') - fn = getattr(cls, opname, None) - fn = getattr(fn, 'im_func',fn) - has_arg = i >= pythonopcode.HAVE_ARGUMENT - #if fn is missing_opcode and not opname.startswith('<') and i>0: - # import warnings - # warnings.warn("* Warning, missing opcode %s" % opname) - opcode_has_arg.append(has_arg) - if has_arg: - fn = fn or missing_opcode_w_arg - dispatch_table_w_arg.append(fn) - dispatch_table_no_arg.append(None) - else: - fn = fn or missing_opcode - dispatch_table_no_arg.append(fn) - dispatch_table_w_arg.append(None) - - cls.opcode_has_arg = opcode_has_arg - cls.dispatch_table_no_arg = dispatch_table_no_arg - cls.dispatch_table_w_arg = dispatch_table_w_arg - - #XXX performance hack! - ### Create dispatch with a lot of if,elifs ### - ### (this gets optimized for translated pypy by the merge_if_blocks transformation) ### - if cls.__name__ != 'PyInterpFrame': - return - import py - - dispatch_code = ''' -def dispatch_translated(self, code, ec): - hint(None, global_merge_point=True) - next_instr = hint(self.next_instr, promote=True) - while True: - hint(None, global_merge_point=True) - self.last_instr = intmask(next_instr) - #ec.bytecode_trace(self) JJJ - #self.next_instr = self.last_instr JJJ - opcode = ord(code[next_instr]) - opcode = hint(opcode, concrete=True) - if self.space.config.objspace.logbytecodes: - self.space.bytecodecounts[opcode] = self.space.bytecodecounts.get(opcode, 0) + 1 - next_instr += 1 - self.next_instr = next_instr - if opcode >= %s: - oparg = ord(code[next_instr]) | ord(code[next_instr + 1]) << 8 - oparg = hint(oparg, concrete=True) - next_instr += 2 - self.next_instr = next_instr - while True: - if opcode == %s: - opcode = ord(code[next_instr]) - opcode = hint(opcode, concrete=True) - oparg = oparg << 16 | ord(code[next_instr + 1]) | ord(code[next_instr + 2]) << 8 - oparg = hint(oparg, concrete=True) - next_instr += 3 - self.next_instr = next_instr - if opcode < %s: - raise pyframe.BytecodeCorruption - continue -''' % (pythonopcode.HAVE_ARGUMENT, - pythonopcode.EXTENDED_ARG, - pythonopcode.HAVE_ARGUMENT) - - def sortkey(opcode, opcodeorder=opcodeorder, ValueError=ValueError): - try: - index = opcodeorder.index(opcode) - except ValueError: - index = 1000000 - return index, opcode - opcases = [(sortkey(i), i, opname) - for opname, i in pythonopcode.opmap.iteritems()] - opcases.sort() # for predictable results - for _, i, opname in opcases: - if i == pythonopcode.EXTENDED_ARG or i < pythonopcode.HAVE_ARGUMENT: - continue - opname = opname.replace('+', '_') - dispatch_code += ' elif opcode == %d:\n' % i - dispatch_code += ' self.%s(oparg)\n' % opname - if opname == 'CALL_FUNCTION': - dispatch_code += ' rstack.resume_point("dispatch_call", self, code, ec)\n' - dispatch_code += ' else:\n' - dispatch_code += ' self.MISSING_OPCODE_W_ARG(oparg)\n' - dispatch_code += ' break\n' +### ____________________________________________________________ ### - for _, i, opname in opcases: - if i >= pythonopcode.HAVE_ARGUMENT: - continue - opname = opname.replace('+', '_') - dispatch_code += ' elif opcode == %d:\n' % i - dispatch_code += ' self.%s()\n' % opname - dispatch_code += ' else:\n' - dispatch_code += ' self.MISSING_OPCODE()\n' - exec py.code.Source(dispatch_code).compile() - cls.dispatch_translated = dispatch_translated - +def cpython_tb(): + """NOT_RPYTHON""" + import sys + return sys.exc_info()[2] +cpython_tb._annspecialcase_ = "override:ignore" + +class Reraise(Exception): + """Signal an application-level OperationError that should not grow + a new traceback entry nor trigger the trace hook.""" + +class BytecodeCorruption(Exception): + """Detected bytecode corruption. Never caught; it's an error.""" + + +### Frame Blocks ### + +class SuspendedUnroller(Wrappable): + """Abstract base class for interpreter-level objects that + instruct the interpreter to change the control flow and the + block stack. + + The concrete subclasses correspond to the various values WHY_XXX + values of the why_code enumeration in ceval.c: + + WHY_NOT, OK, not this one :-) + WHY_EXCEPTION, SApplicationException + WHY_RERAISE, implemented differently, see Reraise + WHY_RETURN, SReturnValue + WHY_BREAK, SBreakLoop + WHY_CONTINUE, SContinueLoop + WHY_YIELD not needed + """ + def nomoreblocks(self): + raise BytecodeCorruption("misplaced bytecode - should not return") + # for the flow object space, a way to "pickle" and "unpickle" the + # ControlFlowException by enumerating the Variables it contains. + def state_unpack_variables(self, space): + return [] # by default, overridden below + def state_pack_variables(self, space, *values_w): + assert len(values_w) == 0 + +class SReturnValue(SuspendedUnroller): + """Signals a 'return' statement. + Argument is the wrapped object to return.""" + kind = 0x01 + def __init__(self, w_returnvalue): + self.w_returnvalue = w_returnvalue + def nomoreblocks(self): + return self.w_returnvalue + def state_unpack_variables(self, space): + return [self.w_returnvalue] + def state_pack_variables(self, space, w_returnvalue): + self.w_returnvalue = w_returnvalue + +class SApplicationException(SuspendedUnroller): + """Signals an application-level exception + (i.e. an OperationException).""" + kind = 0x02 + def __init__(self, operr): + self.operr = operr + def nomoreblocks(self): + raise self.operr + def state_unpack_variables(self, space): + return [self.operr.w_type, self.operr.w_value] + def state_pack_variables(self, space, w_type, w_value): + self.operr = OperationError(w_type, w_value) + +class SBreakLoop(SuspendedUnroller): + """Signals a 'break' statement.""" + kind = 0x04 +SBreakLoop.singleton = SBreakLoop() + +class SContinueLoop(SuspendedUnroller): + """Signals a 'continue' statement. + Argument is the bytecode position of the beginning of the loop.""" + kind = 0x08 + def __init__(self, jump_to): + self.jump_to = jump_to + def state_unpack_variables(self, space): + return [space.wrap(self.jump_to)] + def state_pack_variables(self, space, w_jump_to): + self.jump_to = space.int_w(w_jump_to) + + +class FrameBlock: + + """Abstract base class for frame blocks from the blockstack, + used by the SETUP_XXX and POP_BLOCK opcodes.""" + + def __init__(self, frame, handlerposition): + self.handlerposition = handlerposition + self.valuestackdepth = frame.valuestack.depth() + + def __eq__(self, other): + return (self.__class__ is other.__class__ and + self.handlerposition == other.handlerposition and + self.valuestackdepth == other.valuestackdepth) + + def __ne__(self, other): + return not (self == other) + + def __hash__(self): + return hash((self.handlerposition, self.valuestackdepth)) + + def cleanupstack(self, frame): + for i in range(self.valuestackdepth, frame.valuestack.depth()): + frame.valuestack.pop() + + def cleanup(self, frame): + "Clean up a frame when we normally exit the block." + self.cleanupstack(frame) + + # internal pickling interface, not using the standard protocol + def _get_state_(self, space): + w = space.wrap + return space.newtuple([w(self._opname), w(self.handlerposition), + w(self.valuestackdepth)]) + +class LoopBlock(FrameBlock): + """A loop block. Stores the end-of-loop pointer in case of 'break'.""" + + _opname = 'SETUP_LOOP' + handling_mask = SBreakLoop.kind | SContinueLoop.kind + + def handle(self, frame, unroller): + if isinstance(unroller, SContinueLoop): + # re-push the loop block without cleaning up the value stack, + # and jump to the beginning of the loop, stored in the + # exception's argument + frame.blockstack.push(self) + return unroller.jump_to + else: + # jump to the end of the loop + self.cleanupstack(frame) + return self.handlerposition + + +class ExceptBlock(FrameBlock): + """An try:except: block. Stores the position of the exception handler.""" + + _opname = 'SETUP_EXCEPT' + handling_mask = SApplicationException.kind + + def handle(self, frame, unroller): + # push the exception to the value stack for inspection by the + # exception handler (the code after the except:) + self.cleanupstack(frame) + assert isinstance(unroller, SApplicationException) + operationerr = unroller.operr + if frame.space.full_exceptions: + operationerr.normalize_exception(frame.space) + # the stack setup is slightly different than in CPython: + # instead of the traceback, we store the unroller object, + # wrapped. + frame.valuestack.push(frame.space.wrap(unroller)) + frame.valuestack.push(operationerr.w_value) + frame.valuestack.push(operationerr.w_type) + return self.handlerposition # jump to the handler + + +class FinallyBlock(FrameBlock): + """A try:finally: block. Stores the position of the exception handler.""" + + _opname = 'SETUP_FINALLY' + handling_mask = -1 # handles every kind of SuspendedUnroller + + def cleanup(self, frame): + # upon normal entry into the finally: part, the standard Python + # bytecode pushes a single None for END_FINALLY. In our case we + # always push three values into the stack: the wrapped ctlflowexc, + # the exception value and the exception type (which are all None + # here). + self.cleanupstack(frame) + # one None already pushed by the bytecode + frame.valuestack.push(frame.space.w_None) + frame.valuestack.push(frame.space.w_None) + + def handle(self, frame, unroller): + # any abnormal reason for unrolling a finally: triggers the end of + # the block unrolling and the entering the finally: handler. + # see comments in cleanup(). + self.cleanupstack(frame) + frame.valuestack.push(frame.space.wrap(unroller)) + frame.valuestack.push(frame.space.w_None) + frame.valuestack.push(frame.space.w_None) + return self.handlerposition # jump to the handler + + +block_classes = {'SETUP_LOOP': LoopBlock, + 'SETUP_EXCEPT': ExceptBlock, + 'SETUP_FINALLY': FinallyBlock} ### helpers written at the application-level ### # Some of these functions are expected to be generally useful if other # parts of the code need to do the same thing as a non-trivial opcode, # like finding out which metaclass a new class should have. -# This is why they are not methods of PyInterpFrame. +# This is why they are not methods of PyFrame. # There are also a couple of helpers that are methods, defined in the # class above. Modified: pypy/branch/jit-real-world/pypy/interpreter/test/test_interpreter.py ============================================================================== --- pypy/branch/jit-real-world/pypy/interpreter/test/test_interpreter.py (original) +++ pypy/branch/jit-real-world/pypy/interpreter/test/test_interpreter.py Fri Dec 1 03:43:34 2006 @@ -150,7 +150,7 @@ 1+2+3 + 5+6+7+8+900) def test_import(self): - # Regression test for a bug in PyInterpFrame.IMPORT_NAME: when an + # Regression test for a bug in PyFrame.IMPORT_NAME: when an # import statement was executed in a function without a locals dict, a # plain unwrapped None could be passed into space.call_function causing # assertion errors later on. Modified: pypy/branch/jit-real-world/pypy/interpreter/test/test_pyframe.py ============================================================================== --- pypy/branch/jit-real-world/pypy/interpreter/test/test_pyframe.py (original) +++ pypy/branch/jit-real-world/pypy/interpreter/test/test_pyframe.py Fri Dec 1 03:43:34 2006 @@ -94,6 +94,53 @@ assert len(l) == 1 assert isinstance(l[0][1], Exception) + def test_dont_trace_on_reraise(self): + import sys + l = [] + def ltrace(a,b,c): + if b == 'exception': + l.append(c) + return ltrace + def trace(a,b,c): return ltrace + def f(): + try: + 1/0 + except: + try: + raise + except: + pass + sys.settrace(trace) + f() + sys.settrace(None) + assert len(l) == 1 + assert issubclass(l[0][0], Exception) + + def test_dont_trace_on_raise_with_tb(self): + import sys + l = [] + def ltrace(a,b,c): + if b == 'exception': + l.append(c) + return ltrace + def trace(a,b,c): return ltrace + def f(): + try: + raise Exception + except: + return sys.exc_info() + def g(): + exc, val, tb = f() + try: + raise exc, val, tb + except: + pass + sys.settrace(trace) + g() + sys.settrace(None) + assert len(l) == 1 + assert isinstance(l[0][1], Exception) + def test_trace_changes_locals(self): import sys def trace(frame, what, arg): Modified: pypy/branch/jit-real-world/pypy/interpreter/typedef.py ============================================================================== --- pypy/branch/jit-real-world/pypy/interpreter/typedef.py (original) +++ pypy/branch/jit-real-world/pypy/interpreter/typedef.py Fri Dec 1 03:43:34 2006 @@ -442,7 +442,8 @@ from pypy.interpreter.eval import Code, Frame from pypy.interpreter.pycode import PyCode, CO_VARARGS, CO_VARKEYWORDS -from pypy.interpreter.pyframe import PyFrame, ControlFlowException +from pypy.interpreter.pyframe import PyFrame +from pypy.interpreter.pyopcode import SuspendedUnroller from pypy.interpreter.module import Module from pypy.interpreter.function import Function, Method, StaticMethod from pypy.interpreter.function import BuiltinFunction, descr_function_get @@ -696,7 +697,7 @@ __repr__ = interp2app(NotImplemented.descr__repr__), ) -ControlFlowException.typedef = TypeDef("ControlFlowException") +SuspendedUnroller.typedef = TypeDef("SuspendedUnroller") interptypes = [ val.typedef for name,val in globals().items() if hasattr(val,'__bases__') and hasattr(val,'typedef') ] Modified: pypy/branch/jit-real-world/pypy/module/_pickle_support/maker.py ============================================================================== --- pypy/branch/jit-real-world/pypy/module/_pickle_support/maker.py (original) +++ pypy/branch/jit-real-world/pypy/module/_pickle_support/maker.py Fri Dec 1 03:43:34 2006 @@ -61,11 +61,7 @@ w_pycode, = args_w pycode = space.interp_w(PyCode, w_pycode) w = space.wrap - - # let the code object create the right kind of frame - # the distinction is a little over-done but computable - Klass = pycode.get_frame_class() - new_frame = instantiate(Klass) + new_frame = instantiate(PyFrame) return space.wrap(new_frame) frame_new.unwrap_spec = [ObjSpace, Arguments] @@ -76,13 +72,11 @@ def generator_new(space, __args__): args_w, kwds_w = __args__.unpack() #stolen from std/fake.py - w_frame, w_running, w_exhausted = args_w + w_frame, w_running = args_w frame = space.interp_w(PyFrame, w_frame) running = space.int_w(w_running) - exhausted = space.int_w(w_exhausted) new_generator = GeneratorIterator(frame) new_generator.running = running - new_generator.exhausted = exhausted return space.wrap(new_generator) generator_new.unwrap_spec = [ObjSpace, Arguments] Modified: pypy/branch/jit-real-world/pypy/objspace/flow/flowcontext.py ============================================================================== --- pypy/branch/jit-real-world/pypy/objspace/flow/flowcontext.py (original) +++ pypy/branch/jit-real-world/pypy/objspace/flow/flowcontext.py Fri Dec 1 03:43:34 2006 @@ -95,7 +95,7 @@ def bytecode_trace(self, ec, frame): assert frame is ec.crnt_frame, "seeing an unexpected frame!" - ec.crnt_offset = frame.next_instr # save offset for opcode + ec.crnt_offset = frame.last_instr # save offset for opcode if self.enterspamblock: # If we have a SpamBlock, the first call to bytecode_trace() # occurs as soon as frame.resume() starts, before interpretation @@ -218,8 +218,10 @@ # create an empty frame suitable for the code object # while ignoring any operation like the creation of the locals dict self.recorder = [] - return self.code.create_frame(self.space, self.w_globals, - self.closure) + frame = self.code.create_frame(self.space, self.w_globals, + self.closure) + frame.last_instr = 0 + return frame def bytecode_trace(self, frame): self.recorder.bytecode_trace(self, frame) @@ -256,11 +258,15 @@ except StopFlowing: continue # restarting a dead SpamBlock try: + self.framestack.push(frame) self.crnt_frame = frame try: - w_result = frame.resume() + w_result = frame.dispatch(frame.pycode.co_code, + frame.last_instr, + self) finally: self.crnt_frame = None + self.framestack.pop() except OperationThatShouldNotBePropagatedError, e: raise Exception( Modified: pypy/branch/jit-real-world/pypy/objspace/flow/framestate.py ============================================================================== --- pypy/branch/jit-real-world/pypy/objspace/flow/framestate.py (original) +++ pypy/branch/jit-real-world/pypy/objspace/flow/framestate.py Fri Dec 1 03:43:34 2006 @@ -1,4 +1,5 @@ -from pypy.interpreter.pyframe import PyFrame, SuspendedUnroller +from pypy.interpreter.pyframe import PyFrame +from pypy.interpreter.pyopcode import SuspendedUnroller from pypy.interpreter.error import OperationError from pypy.rlib.objectmodel import instantiate from pypy.rlib.unroll import SpecTag @@ -21,7 +22,7 @@ self.mergeable = data self.nonmergeable = ( state.blockstack.items[:], - state.next_instr, + state.last_instr, # == next_instr when between bytecodes state.w_locals, ) elif isinstance(state, tuple): @@ -48,7 +49,7 @@ frame.last_exception = OperationError(data[-2], data[-1]) ( frame.blockstack.items[:], - frame.next_instr, + frame.last_instr, frame.w_locals, ) = self.nonmergeable else: @@ -157,9 +158,9 @@ isinstance(item.value, SuspendedUnroller)): i += 1 else: - flowexc = item.value.flowexc - vars = flowexc.state_unpack_variables(space) - key = flowexc.__class__, len(vars) + unroller = item.value + vars = unroller.state_unpack_variables(space) + key = unroller.__class__, len(vars) try: tag = PICKLE_TAGS[key] except: @@ -171,9 +172,9 @@ for i in range(len(lst)-1, -1, -1): item = lst[i] if item in UNPICKLE_TAGS: - flowexcclass, argcount = UNPICKLE_TAGS[item] + unrollerclass, argcount = UNPICKLE_TAGS[item] arguments = lst[i+1: i+1+argcount] del lst[i+1: i+1+argcount] - flowexc = instantiate(flowexcclass) - flowexc.state_pack_variables(space, *arguments) - lst[i] = flowexc.wrap(space) + unroller = instantiate(unrollerclass) + unroller.state_pack_variables(space, *arguments) + lst[i] = space.wrap(unroller) Modified: pypy/branch/jit-real-world/pypy/tool/stdlib_opcode.py ============================================================================== --- pypy/branch/jit-real-world/pypy/tool/stdlib_opcode.py (original) +++ pypy/branch/jit-real-world/pypy/tool/stdlib_opcode.py Fri Dec 1 03:43:34 2006 @@ -1,9 +1,76 @@ # load opcode.py as pythonopcode from our own lib -# This should handle missing local copy + +__all__ = ['opmap', 'opname', 'HAVE_ARGUMENT', + 'hasjrel', 'hasjabs', 'cmp_op'] + def load_opcode(): import py opcode_path = py.path.local(__file__).dirpath().dirpath().dirpath('lib-python/modified-2.4.1/opcode.py') - execfile(str(opcode_path), globals()) + d = {} + execfile(str(opcode_path), d) + return d -load_opcode() +opcode_dict = load_opcode() del load_opcode + +# copy some stuff from opcode.py directly into our globals +for name in __all__: + if name in opcode_dict: + globals()[name] = opcode_dict[name] + +opcode_method_names = ['MISSING_OPCODE'] * 256 +for name, index in opmap.items(): + opcode_method_names[index] = name.replace('+', '_') + +# ____________________________________________________________ +# RPython-friendly helpers and structures + +from pypy.rlib.unroll import unrolling_iterable + + +class OpcodeDesc(object): + def __init__(self, name, index): + self.name = name + self.methodname = opcode_method_names[index] + self.index = index + self.hasarg = index >= HAVE_ARGUMENT + + def _freeze_(self): + return True + + def is_enabled(self, space): + """Check if the opcode should be enabled in the space's configuration. + (Returns True for all standard opcodes.)""" + opt = space.config.objspace.opcodes + return getattr(opt, self.name, True) + is_enabled._annspecialcase_ = 'specialize:memo' + + # for predictable results, we try to order opcodes most-used-first + opcodeorder = [124, 125, 100, 105, 1, 131, 116, 111, 106, 83, 23, 93, 113, 25, 95, 64, 112, 66, 102, 110, 60, 92, 62, 120, 68, 87, 32, 136, 4, 103, 24, 63, 18, 65, 15, 55, 121, 3, 101, 22, 12, 80, 86, 135, 126, 90, 140, 104, 2, 33, 20, 108, 107, 31, 134, 132, 88, 30, 133, 130, 137, 141, 61, 122, 11, 40, 74, 73, 51, 96, 21, 42, 56, 85, 82, 89, 142, 77, 78, 79, 91, 76, 97, 57, 19, 43, 84, 50, 41, 99, 53, 26] + + def sortkey(self): + try: + i = self.opcodeorder.index(self.index) + except ValueError: + i = 1000000 + return i, self.index + + def __cmp__(self, other): + return cmp(self.sortkey(), other.sortkey()) + + +opdescmap = {} + +class opcodedesc: + """A namespace mapping OPCODE_NAME to OpcodeDescs.""" + +for name, index in opmap.items(): + desc = OpcodeDesc(name, index) + setattr(opcodedesc, name, desc) + opdescmap[index] = desc + +lst = opdescmap.values() +lst.sort() +unrolling_opcode_descs = unrolling_iterable(lst) + +del name, index, desc, lst From fijal at codespeak.net Fri Dec 1 10:46:50 2006 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 1 Dec 2006 10:46:50 +0100 (CET) Subject: [pypy-svn] r35188 - pypy/dist/pypy/module/thread/rpython/test Message-ID: <20061201094650.13BD310068@code0.codespeak.net> Author: fijal Date: Fri Dec 1 10:46:47 2006 New Revision: 35188 Modified: pypy/dist/pypy/module/thread/rpython/test/test_ll_thread.py Log: Added a skip when threads are not there. Modified: pypy/dist/pypy/module/thread/rpython/test/test_ll_thread.py ============================================================================== --- pypy/dist/pypy/module/thread/rpython/test/test_ll_thread.py (original) +++ pypy/dist/pypy/module/thread/rpython/test/test_ll_thread.py Fri Dec 1 10:46:47 2006 @@ -1,4 +1,7 @@ -import thread +try: + import thread +except ImportError: + py.test.skip("Threads not supported") import pypy.module.thread.rpython.exttable # for declare()/declaretype() from pypy.module.thread.rpython.ll_thread import * from pypy.annotation.annrpython import RPythonAnnotator From fijal at codespeak.net Fri Dec 1 10:48:19 2006 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 1 Dec 2006 10:48:19 +0100 (CET) Subject: [pypy-svn] r35189 - in pypy/dist/pypy/module/posix: . test Message-ID: <20061201094819.4005D1006C@code0.codespeak.net> Author: fijal Date: Fri Dec 1 10:48:17 2006 New Revision: 35189 Modified: pypy/dist/pypy/module/posix/__init__.py pypy/dist/pypy/module/posix/interp_posix.py pypy/dist/pypy/module/posix/test/test_posix2.py Log: Added (module-level) os.execv Modified: pypy/dist/pypy/module/posix/__init__.py ============================================================================== --- pypy/dist/pypy/module/posix/__init__.py (original) +++ pypy/dist/pypy/module/posix/__init__.py Fri Dec 1 10:48:17 2006 @@ -70,6 +70,8 @@ interpleveldefs['fork'] = 'interp_posix.fork' if hasattr(os, 'waitpid'): interpleveldefs['waitpid'] = 'interp_posix.waitpid' + if hasattr(os, 'execv'): + interpleveldefs['execv'] = 'interp_posix.execv' #if hasattr(ctypes_posix, 'uname'): # interpleveldefs['uname'] = 'interp_posix.uname' 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 Fri Dec 1 10:48:17 2006 @@ -1,4 +1,4 @@ -from pypy.interpreter.baseobjspace import ObjSpace +from pypy.interpreter.baseobjspace import ObjSpace, W_Root from pypy.rlib.rarithmetic import intmask from pypy.rlib import ros from pypy.interpreter.error import OperationError @@ -398,6 +398,10 @@ return space.wrap(intmask(_c.geteuid())) geteuid.unwrap_spec = [ObjSpace] +def execv(space, command, w_args): + os.execv(command, [space.str_w(i) for i in space.unpackiterable(w_args)]) +execv.unwrap_spec = [ObjSpace, str, W_Root] + def uname(space): try: result = _c.uname() Modified: pypy/dist/pypy/module/posix/test/test_posix2.py ============================================================================== --- pypy/dist/pypy/module/posix/test/test_posix2.py (original) +++ pypy/dist/pypy/module/posix/test/test_posix2.py Fri Dec 1 10:48:17 2006 @@ -101,6 +101,16 @@ assert pid1 == pid # XXX check status1 + if hasattr(__import__(os.name), "execv"): # and fork + def test_execv(self): + os = self.posix + pid = os.fork() + if pid == 0: + os.execv("/usr/bin/env", ["env", "python", "-c", "open('onefile', 'w').write('1')"]) + os.waitpid(pid, 0) + assert open("onefile").read() == "1" + os.unlink("onefile") + class AppTestEnvironment(object): def setup_class(cls): cls.space = space From fijal at codespeak.net Fri Dec 1 10:49:46 2006 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 1 Dec 2006 10:49:46 +0100 (CET) Subject: [pypy-svn] r35190 - in pypy/dist/pypy: rpython rpython/module translator/c translator/c/src translator/c/test Message-ID: <20061201094946.79A6310071@code0.codespeak.net> Author: fijal Date: Fri Dec 1 10:49:43 2006 New Revision: 35190 Modified: pypy/dist/pypy/rpython/extfunctable.py pypy/dist/pypy/rpython/module/ll_os.py pypy/dist/pypy/translator/c/extfunc.py pypy/dist/pypy/translator/c/src/ll_os.h pypy/dist/pypy/translator/c/test/test_extfunc.py Log: Added os.execv Modified: pypy/dist/pypy/rpython/extfunctable.py ============================================================================== --- pypy/dist/pypy/rpython/extfunctable.py (original) +++ pypy/dist/pypy/rpython/extfunctable.py Fri Dec 1 10:49:43 2006 @@ -233,6 +233,8 @@ declare(os.spawnv, int, 'll_os/spawnv') if hasattr(os, 'waitpid'): declare(os.waitpid , waitpidannotation, 'll_os/waitpid') +if hasattr(os, 'execv'): + declare(os.execv, noneannotation, 'll_os/execv') declare(os.path.exists, bool , 'll_os_path/exists') declare(os.path.isdir, bool , 'll_os_path/isdir') 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 Fri Dec 1 10:49:43 2006 @@ -96,6 +96,10 @@ return os.system(cls.from_rstr(cmd)) ll_os_system.suggested_primitive = True + def ll_os_execv(cls, cmd, args): + os.execv(cmd, args) + ll_os_execv.suggested_primitive = True + def ll_os_unlink(cls, path): os.unlink(cls.from_rstr(path)) ll_os_unlink.suggested_primitive = True Modified: pypy/dist/pypy/translator/c/extfunc.py ============================================================================== --- pypy/dist/pypy/translator/c/extfunc.py (original) +++ pypy/dist/pypy/translator/c/extfunc.py Fri Dec 1 10:49:43 2006 @@ -60,6 +60,7 @@ impl.ll_os_spawnv.im_func: 'LL_os_spawnv', impl.ll_os_waitpid.im_func: 'LL_os_waitpid', impl.ll_os__exit.im_func: 'LL_os__exit', + impl.ll_os_execv.im_func: 'LL_os_execv', ll_time.ll_time_clock: 'LL_time_clock', ll_time.ll_time_sleep: 'LL_time_sleep', ll_time.ll_time_time: 'LL_time_time', Modified: pypy/dist/pypy/translator/c/src/ll_os.h ============================================================================== --- pypy/dist/pypy/translator/c/src/ll_os.h (original) +++ pypy/dist/pypy/translator/c/src/ll_os.h Fri Dec 1 10:49:43 2006 @@ -80,6 +80,7 @@ long LL_readlink_into(RPyString *path, RPyString *buffer); long LL_os_fork(void); #ifdef HAVE_RPY_LIST_OF_STRING /* argh */ +void LL_os_execv(RPyString *cmd, RPyListOfString *args); long LL_os_spawnv(int mode, RPyString *path, RPyListOfString *args); #endif RPyWAITPID_RESULT* LL_os_waitpid(long pid, long options); @@ -389,6 +390,20 @@ } #endif +#if defined(HAVE_EXECV) && defined(HAVE_RPY_LIST_OF_STRING) +void LL_os_execv(RPyString *cmd, RPyListOfString *args) { + int i, nargs = args->l_length; + char **slist = malloc((nargs+1) * sizeof(char*)); + if (slist) { + for (i=0; il_items->items[i]); + slist[nargs] = NULL; + execv(RPyString_AsString(cmd), slist); + } /* should never return */ + RPYTHON_RAISE_OSERROR(errno); +} +#endif + /* The following code is only generated if spawnv exists and if RPyListOfString exists. The latter is a bit tricky: Modified: pypy/dist/pypy/translator/c/test/test_extfunc.py ============================================================================== --- pypy/dist/pypy/translator/c/test/test_extfunc.py (original) +++ pypy/dist/pypy/translator/c/test/test_extfunc.py Fri Dec 1 10:49:43 2006 @@ -5,6 +5,7 @@ from pypy.translator.c.test.test_genc import compile from pypy.translator.c.extfunc import EXTERNALS from pypy.rlib import ros +from pypy.translator.stackless.test.test_transform import one def test_all_suggested_primitives(): for modulename in ['ll_math', 'll_os', 'll_os_path', 'll_time']: @@ -684,3 +685,20 @@ compared_with.sort() assert result == compared_with +if hasattr(posix, 'execv'): + def test_execv(): + filename = str(udir.join('test_execv.txt')) + def does_stuff(): + progname = str(sys.executable) + l = [] + l.append(progname) + l += ["-c", 'open("%s","w").write("1")' % filename] + pid = os.fork() + if pid == 0: + os.execv(progname, l) + else: + os.waitpid(pid, 0) + func = compile(does_stuff, []) + func() + assert open(filename).read() == "1" + From cfbolz at codespeak.net Fri Dec 1 11:09:10 2006 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Fri, 1 Dec 2006 11:09:10 +0100 (CET) Subject: [pypy-svn] r35191 - pypy/dist/pypy/objspace/std/test Message-ID: <20061201100910.D65FF10071@code0.codespeak.net> Author: cfbolz Date: Fri Dec 1 11:09:09 2006 New Revision: 35191 Modified: pypy/dist/pypy/objspace/std/test/test_userobject.py Log: dict subclassing works just fine now Modified: pypy/dist/pypy/objspace/std/test/test_userobject.py ============================================================================== --- pypy/dist/pypy/objspace/std/test/test_userobject.py (original) +++ pypy/dist/pypy/objspace/std/test/test_userobject.py Fri Dec 1 11:09:09 2006 @@ -25,16 +25,10 @@ def test_subclassing(self): for base in tuple, list, dict, str, int, float: - try: - class subclass(base): pass - stuff = subclass() - except: - print 'not subclassable:', base - if base is not dict: # XXX must be fixed - raise - else: - assert isinstance(stuff, base) - assert subclass.__base__ is base + class subclass(base): pass + stuff = subclass() + assert isinstance(stuff, base) + assert subclass.__base__ is base def test_subclasstuple(self): class subclass(tuple): pass From xoraxax at codespeak.net Fri Dec 1 11:19:43 2006 From: xoraxax at codespeak.net (xoraxax at codespeak.net) Date: Fri, 1 Dec 2006 11:19:43 +0100 (CET) Subject: [pypy-svn] r35192 - pypy/dist/pypy/doc Message-ID: <20061201101943.E5F9C10061@code0.codespeak.net> Author: xoraxax Date: Fri Dec 1 11:19:42 2006 New Revision: 35192 Modified: pypy/dist/pypy/doc/getting-started.txt Log: Added explicit hint to install Boehm. Modified: pypy/dist/pypy/doc/getting-started.txt ============================================================================== --- pypy/dist/pypy/doc/getting-started.txt (original) +++ pypy/dist/pypy/doc/getting-started.txt Fri Dec 1 11:19:42 2006 @@ -528,7 +528,9 @@ By default the translation process will try to use the `Boehm-Demers-Weiser garbage collector`_ for the translated PyPy (Use ``--gc=ref`` to use our own reference counting implementation which -at the moment is slower but doesn't have external dependencies). +at the moment is slower but doesn't have external dependencies). Be sure +to install Boehm before starting the translation (e.g. by running +``apt-get install libgc-dev`` on Debian). This whole process will take some time and quite a lot of memory. To reduce the memory footprint of the translation process you can use the From xoraxax at codespeak.net Fri Dec 1 11:24:21 2006 From: xoraxax at codespeak.net (xoraxax at codespeak.net) Date: Fri, 1 Dec 2006 11:24:21 +0100 (CET) Subject: [pypy-svn] r35193 - pypy/dist/pypy/doc Message-ID: <20061201102421.4259F10071@code0.codespeak.net> Author: xoraxax Date: Fri Dec 1 11:24:19 2006 New Revision: 35193 Modified: pypy/dist/pypy/doc/getting-started.txt Log: Ensured continuity by adding the word "Otherwise". Modified: pypy/dist/pypy/doc/getting-started.txt ============================================================================== --- pypy/dist/pypy/doc/getting-started.txt (original) +++ pypy/dist/pypy/doc/getting-started.txt Fri Dec 1 11:24:19 2006 @@ -528,7 +528,7 @@ By default the translation process will try to use the `Boehm-Demers-Weiser garbage collector`_ for the translated PyPy (Use ``--gc=ref`` to use our own reference counting implementation which -at the moment is slower but doesn't have external dependencies). Be sure +at the moment is slower but doesn't have external dependencies). Otherwise, be sure to install Boehm before starting the translation (e.g. by running ``apt-get install libgc-dev`` on Debian). From arigo at codespeak.net Fri Dec 1 12:41:48 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 1 Dec 2006 12:41:48 +0100 (CET) Subject: [pypy-svn] r35194 - in pypy/dist/pypy: objspace/flow/test rlib Message-ID: <20061201114148.58F2710061@code0.codespeak.net> Author: arigo Date: Fri Dec 1 12:41:45 2006 New Revision: 35194 Modified: pypy/dist/pypy/objspace/flow/test/test_unroll.py pypy/dist/pypy/rlib/unroll.py Log: Fix a combinatorical explosion when unrolling loops with "if" statements. Done by caching the _unroller SpecTags, instead of making fresh ones even for the same indices. Modified: pypy/dist/pypy/objspace/flow/test/test_unroll.py ============================================================================== --- pypy/dist/pypy/objspace/flow/test/test_unroll.py (original) +++ pypy/dist/pypy/objspace/flow/test/test_unroll.py Fri Dec 1 12:41:45 2006 @@ -1,3 +1,4 @@ +import operator from pypy.objspace.flow.test.test_objspace import Base from pypy.rlib.unroll import unrolling_zero, unrolling_iterable @@ -38,3 +39,28 @@ graph = self.codetest(f) ops = self.all_operations(graph) assert ops == {'setattr': 3} + + def test_unroll_ifs(self): + operations = unrolling_iterable([operator.lt, + operator.le, + operator.eq, + operator.ne, + operator.gt, + operator.ge]) + def accept(n): + "stub" + def f(x, y): + for op in operations: + if accept(op): + op(x, y) + + graph = self.codetest(f) + ops = self.all_operations(graph) + assert ops == {'simple_call': 6, + 'is_true': 6, + 'lt': 1, + 'le': 1, + 'eq': 1, + 'ne': 1, + 'gt': 1, + 'ge': 1} Modified: pypy/dist/pypy/rlib/unroll.py ============================================================================== --- pypy/dist/pypy/rlib/unroll.py (original) +++ pypy/dist/pypy/rlib/unroll.py Fri Dec 1 12:41:45 2006 @@ -43,12 +43,13 @@ def __init__(self, iterable): self._items = list(iterable) + self._head = _unroller(self._items) def __iter__(self): return iter(self._items) def get_unroller(self): - return _unroller(self._items) + return self._head class _unroller(SpecTag): @@ -56,8 +57,10 @@ def __init__(self, items, i=0): self._items = items self._i = i + self._next = None def step(self): v = self._items[self._i] - next = _unroller(self._items, self._i+1) - return v, next + if self._next is None: + self._next = _unroller(self._items, self._i+1) + return v, self._next From arigo at codespeak.net Fri Dec 1 12:43:03 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 1 Dec 2006 12:43:03 +0100 (CET) Subject: [pypy-svn] r35195 - pypy/branch/jit-real-world/pypy/interpreter Message-ID: <20061201114303.B54B010068@code0.codespeak.net> Author: arigo Date: Fri Dec 1 12:43:01 2006 New Revision: 35195 Modified: pypy/branch/jit-real-world/pypy/interpreter/pyopcode.py Log: Fix a typo, move a bit of code out of dispatch_bytecode(). Modified: pypy/branch/jit-real-world/pypy/interpreter/pyopcode.py ============================================================================== --- pypy/branch/jit-real-world/pypy/interpreter/pyopcode.py (original) +++ pypy/branch/jit-real-world/pypy/interpreter/pyopcode.py Fri Dec 1 12:43:01 2006 @@ -62,7 +62,7 @@ except MemoryError: next_instr = self.handle_asynchronous_error(ec, self.space.w_MemoryError) - except RuntimeError: + except RuntimeError, e: if we_are_translated(): # stack overflows should be the only kind of RuntimeErrors # in translated PyPy @@ -131,7 +131,6 @@ w_returnvalue = self.valuestack.pop() block = self.unrollstack(SReturnValue.kind) if block is None: - self.frame_finished_execution = True # for generators return w_returnvalue else: unroller = SReturnValue(w_returnvalue) @@ -143,20 +142,11 @@ return w_yieldvalue if opcode == opcodedesc.END_FINALLY.index: - # unlike CPython, when we reach this opcode the value stack has - # always been set up as follows (topmost first): - # [exception type or None] - # [exception value or None] - # [wrapped stack unroller ] - self.valuestack.pop() # ignore the exception type - self.valuestack.pop() # ignore the exception value - w_unroller = self.valuestack.pop() - unroller = self.space.interpclass_w(w_unroller) + unroller = self.end_finally() if isinstance(unroller, SuspendedUnroller): # go on unrolling the stack block = self.unrollstack(unroller.kind) if block is None: - self.frame_finished_execution = True # for generators return unroller.nomoreblocks() else: next_instr = block.handle(self, unroller) @@ -194,6 +184,8 @@ block = self.blockstack.pop() if (block.handling_mask & unroller_kind) != 0: return block + block.cleanupstack(self) + self.frame_finished_execution = True # for generators return None def unrollstack_and_jump(self, unroller): @@ -504,6 +496,18 @@ block = f.blockstack.pop() block.cleanup(f) # the block knows how to clean up the value stack + def end_finally(f): + # unlike CPython, when we reach this opcode the value stack has + # always been set up as follows (topmost first): + # [exception type or None] + # [exception value or None] + # [wrapped stack unroller ] + f.valuestack.pop() # ignore the exception type + f.valuestack.pop() # ignore the exception value + w_unroller = f.valuestack.pop() + unroller = f.space.interpclass_w(w_unroller) + return unroller + def BUILD_CLASS(f, *ignored): w_methodsdict = f.valuestack.pop() w_bases = f.valuestack.pop() From arigo at codespeak.net Fri Dec 1 12:43:34 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 1 Dec 2006 12:43:34 +0100 (CET) Subject: [pypy-svn] r35196 - in pypy/branch/jit-real-world/pypy: objspace/flow/test rlib Message-ID: <20061201114334.B3E0B1006E@code0.codespeak.net> Author: arigo Date: Fri Dec 1 12:43:32 2006 New Revision: 35196 Modified: pypy/branch/jit-real-world/pypy/objspace/flow/test/test_unroll.py pypy/branch/jit-real-world/pypy/rlib/unroll.py Log: Port of r35194. Modified: pypy/branch/jit-real-world/pypy/objspace/flow/test/test_unroll.py ============================================================================== --- pypy/branch/jit-real-world/pypy/objspace/flow/test/test_unroll.py (original) +++ pypy/branch/jit-real-world/pypy/objspace/flow/test/test_unroll.py Fri Dec 1 12:43:32 2006 @@ -1,3 +1,4 @@ +import operator from pypy.objspace.flow.test.test_objspace import Base from pypy.rlib.unroll import unrolling_zero, unrolling_iterable @@ -38,3 +39,28 @@ graph = self.codetest(f) ops = self.all_operations(graph) assert ops == {'setattr': 3} + + def test_unroll_ifs(self): + operations = unrolling_iterable([operator.lt, + operator.le, + operator.eq, + operator.ne, + operator.gt, + operator.ge]) + def accept(n): + "stub" + def f(x, y): + for op in operations: + if accept(op): + op(x, y) + + graph = self.codetest(f) + ops = self.all_operations(graph) + assert ops == {'simple_call': 6, + 'is_true': 6, + 'lt': 1, + 'le': 1, + 'eq': 1, + 'ne': 1, + 'gt': 1, + 'ge': 1} Modified: pypy/branch/jit-real-world/pypy/rlib/unroll.py ============================================================================== --- pypy/branch/jit-real-world/pypy/rlib/unroll.py (original) +++ pypy/branch/jit-real-world/pypy/rlib/unroll.py Fri Dec 1 12:43:32 2006 @@ -43,12 +43,13 @@ def __init__(self, iterable): self._items = list(iterable) + self._head = _unroller(self._items) def __iter__(self): return iter(self._items) def get_unroller(self): - return _unroller(self._items) + return self._head class _unroller(SpecTag): @@ -56,8 +57,10 @@ def __init__(self, items, i=0): self._items = items self._i = i + self._next = None def step(self): v = self._items[self._i] - next = _unroller(self._items, self._i+1) - return v, next + if self._next is None: + self._next = _unroller(self._items, self._i+1) + return v, self._next From arigo at codespeak.net Fri Dec 1 13:12:46 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 1 Dec 2006 13:12:46 +0100 (CET) Subject: [pypy-svn] r35197 - pypy/branch/jit-real-world/pypy/interpreter Message-ID: <20061201121246.1225C10068@code0.codespeak.net> Author: arigo Date: Fri Dec 1 13:12:44 2006 New Revision: 35197 Modified: pypy/branch/jit-real-world/pypy/interpreter/pyopcode.py Log: (arigo, arre in parallel) Work around bad support for "raise Class, instance" in the flow space. Modified: pypy/branch/jit-real-world/pypy/interpreter/pyopcode.py ============================================================================== --- pypy/branch/jit-real-world/pypy/interpreter/pyopcode.py (original) +++ pypy/branch/jit-real-world/pypy/interpreter/pyopcode.py Fri Dec 1 13:12:44 2006 @@ -91,8 +91,13 @@ block = self.unrollstack(SApplicationException.kind) if block is None: # no handler found for the OperationError - tb = cpython_tb() - raise OperationError, operr, tb + if we_are_translated(): + raise operr + else: + # try to preserve the CPython-level traceback + import sys + tb = sys.exc_info()[2] + raise OperationError, operr, tb else: unroller = SApplicationException(operr) next_instr = block.handle(self, unroller) @@ -868,13 +873,6 @@ ### ____________________________________________________________ ### - -def cpython_tb(): - """NOT_RPYTHON""" - import sys - return sys.exc_info()[2] -cpython_tb._annspecialcase_ = "override:ignore" - class Reraise(Exception): """Signal an application-level OperationError that should not grow a new traceback entry nor trigger the trace hook.""" From arigo at codespeak.net Fri Dec 1 13:22:41 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 1 Dec 2006 13:22:41 +0100 (CET) Subject: [pypy-svn] r35198 - in pypy/branch/jit-real-world/pypy: interpreter objspace/flow Message-ID: <20061201122241.57B3510068@code0.codespeak.net> Author: arigo Date: Fri Dec 1 13:22:38 2006 New Revision: 35198 Modified: pypy/branch/jit-real-world/pypy/interpreter/pyopcode.py pypy/branch/jit-real-world/pypy/objspace/flow/framestate.py Log: Turn state_pack_variables() into a "constructor" static method, instead of using instantiate() in the flow space. This avoids making multiple instances of SBreakLoop (needed for flowgraphing the BREAK_LOOP function itself, which manipulates the singleton directly). Modified: pypy/branch/jit-real-world/pypy/interpreter/pyopcode.py ============================================================================== --- pypy/branch/jit-real-world/pypy/interpreter/pyopcode.py (original) +++ pypy/branch/jit-real-world/pypy/interpreter/pyopcode.py Fri Dec 1 13:22:38 2006 @@ -901,12 +901,10 @@ """ def nomoreblocks(self): raise BytecodeCorruption("misplaced bytecode - should not return") - # for the flow object space, a way to "pickle" and "unpickle" the - # ControlFlowException by enumerating the Variables it contains. - def state_unpack_variables(self, space): - return [] # by default, overridden below - def state_pack_variables(self, space, *values_w): - assert len(values_w) == 0 + + # NB. for the flow object space, the state_(un)pack_variables methods + # give a way to "pickle" and "unpickle" the SuspendedUnroller by + # enumerating the Variables it contains. class SReturnValue(SuspendedUnroller): """Signals a 'return' statement. @@ -916,10 +914,12 @@ self.w_returnvalue = w_returnvalue def nomoreblocks(self): return self.w_returnvalue + def state_unpack_variables(self, space): return [self.w_returnvalue] - def state_pack_variables(self, space, w_returnvalue): - self.w_returnvalue = w_returnvalue + def state_pack_variables(space, w_returnvalue): + return SReturnValue(w_returnvalue) + state_pack_variables = staticmethod(state_pack_variables) class SApplicationException(SuspendedUnroller): """Signals an application-level exception @@ -929,14 +929,23 @@ self.operr = operr def nomoreblocks(self): raise self.operr + def state_unpack_variables(self, space): return [self.operr.w_type, self.operr.w_value] - def state_pack_variables(self, space, w_type, w_value): - self.operr = OperationError(w_type, w_value) + def state_pack_variables(space, w_type, w_value): + return SApplicationException(OperationError(w_type, w_value)) + state_pack_variables = staticmethod(state_pack_variables) class SBreakLoop(SuspendedUnroller): """Signals a 'break' statement.""" kind = 0x04 + + def state_unpack_variables(self, space): + return [] + def state_pack_variables(space): + return SBreakLoop.singleton + state_pack_variables = staticmethod(state_pack_variables) + SBreakLoop.singleton = SBreakLoop() class SContinueLoop(SuspendedUnroller): @@ -945,10 +954,12 @@ kind = 0x08 def __init__(self, jump_to): self.jump_to = jump_to + def state_unpack_variables(self, space): return [space.wrap(self.jump_to)] - def state_pack_variables(self, space, w_jump_to): - self.jump_to = space.int_w(w_jump_to) + def state_pack_variables(space, w_jump_to): + return SContinueLoop(space.int_w(w_jump_to)) + state_pack_variables = staticmethod(state_pack_variables) class FrameBlock: Modified: pypy/branch/jit-real-world/pypy/objspace/flow/framestate.py ============================================================================== --- pypy/branch/jit-real-world/pypy/objspace/flow/framestate.py (original) +++ pypy/branch/jit-real-world/pypy/objspace/flow/framestate.py Fri Dec 1 13:22:38 2006 @@ -1,7 +1,6 @@ from pypy.interpreter.pyframe import PyFrame from pypy.interpreter.pyopcode import SuspendedUnroller from pypy.interpreter.error import OperationError -from pypy.rlib.objectmodel import instantiate from pypy.rlib.unroll import SpecTag from pypy.objspace.flow.model import * @@ -175,6 +174,5 @@ unrollerclass, argcount = UNPICKLE_TAGS[item] arguments = lst[i+1: i+1+argcount] del lst[i+1: i+1+argcount] - unroller = instantiate(unrollerclass) - unroller.state_pack_variables(space, *arguments) + unroller = unrollerclass.state_pack_variables(space, *arguments) lst[i] = space.wrap(unroller) From fijal at codespeak.net Fri Dec 1 16:43:36 2006 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 1 Dec 2006 16:43:36 +0100 (CET) Subject: [pypy-svn] r35203 - pypy/dist/pypy/translator/c/src Message-ID: <20061201154336.3036D10063@code0.codespeak.net> Author: fijal Date: Fri Dec 1 16:43:34 2006 New Revision: 35203 Modified: pypy/dist/pypy/translator/c/src/support.h Log: Seems that symbol has Modified: pypy/dist/pypy/translator/c/src/support.h ============================================================================== --- pypy/dist/pypy/translator/c/src/support.h (original) +++ pypy/dist/pypy/translator/c/src/support.h Fri Dec 1 16:43:34 2006 @@ -45,7 +45,7 @@ # define RPyAssert(x, msg) /* nothing */ #endif -#ifdef __RPyListOfString_New /* :-( */ +#ifdef _RPyListOfString_New /* :-( */ # define HAVE_RPY_LIST_OF_STRING #endif From ericvrp at codespeak.net Fri Dec 1 17:30:15 2006 From: ericvrp at codespeak.net (ericvrp at codespeak.net) Date: Fri, 1 Dec 2006 17:30:15 +0100 (CET) Subject: [pypy-svn] r35204 - in pypy/dist/pypy/jit/codegen/llvm: . lib test Message-ID: <20061201163015.5492E10076@code0.codespeak.net> Author: ericvrp Date: Fri Dec 1 17:30:13 2006 New Revision: 35204 Modified: pypy/dist/pypy/jit/codegen/llvm/lib/libllvmjit.cpp pypy/dist/pypy/jit/codegen/llvm/lib/libllvmjit.h pypy/dist/pypy/jit/codegen/llvm/llvmjit.py pypy/dist/pypy/jit/codegen/llvm/test/test_llvmjit.py Log: llvmjit test_call_global_function is working. Some function renaming to stay closer to the llvm names. Modified: pypy/dist/pypy/jit/codegen/llvm/lib/libllvmjit.cpp ============================================================================== --- pypy/dist/pypy/jit/codegen/llvm/lib/libllvmjit.cpp (original) +++ pypy/dist/pypy/jit/codegen/llvm/lib/libllvmjit.cpp Fri Dec 1 17:30:13 2006 @@ -86,11 +86,7 @@ } -void* find_function(const char* name) { - return gp_execution_engine->FindFunctionNamed(name); //note: can be NULL -} - - +//Function methods int freeMachineCodeForFunction(const void* function) { if (!function) { std::cerr << "No function supplied to libllvmjit.freeMachineCodeForFunction(...)\n" << std::flush; @@ -127,6 +123,7 @@ } +//code for testcases int get_global_data() { return g_data; } @@ -137,14 +134,37 @@ } -int* get_pointer_to_global_data() { +int* get_pointer_to_global_data() { return &g_data; } -void add_global_mapping(const char* name, void* address) { - //note: using getNamedGlobal implies that we can not have globals of different type - // but with identical names! This is probably easy to do. - gp_execution_engine->addGlobalMapping(gp_module->getNamedGlobal(name), address); +int global_function(int a, int b, int c) { + return a + b + c; +} + + +void* get_pointer_to_global_function() { + return (void*)global_function; //note: we don't care about the actual signature here +} + + +// Module methods +void* getNamedFunction(const char* name) { + return gp_module->getNamedFunction(name); //note: can be NULL +} + + +void* getNamedGlobal(const char* name) { + return gp_module->getNamedGlobal(name); //note: can be NULL +} + + +void addGlobalMapping(const void* p, void* address) { + if (!p) { + std::cerr << "No global variable or function supplied to addGlobalMapping\n" << std::flush; + return; + } + gp_execution_engine->addGlobalMapping((const GlobalValue*)p, address); } Modified: pypy/dist/pypy/jit/codegen/llvm/lib/libllvmjit.h ============================================================================== --- pypy/dist/pypy/jit/codegen/llvm/lib/libllvmjit.h (original) +++ pypy/dist/pypy/jit/codegen/llvm/lib/libllvmjit.h Fri Dec 1 17:30:13 2006 @@ -7,14 +7,22 @@ void restart(); int transform(const char* passnames); int parse(const char* llsource); -void* find_function(const char* funcname); + +//Function code int freeMachineCodeForFunction(const void* function); int recompile(const void* function); int execute(const void* function, int param); + +//Module code +void* getNamedFunction(const char* name); +void* getNamedGlobal(const char* name); +void addGlobalMapping(const void* p, void* address); + +//test code int get_global_data(); void set_global_data(int n); int* get_pointer_to_global_data(); -void add_global_mapping(const char* name, void* address); +void* get_pointer_to_global_function(); #ifdef __cplusplus } Modified: pypy/dist/pypy/jit/codegen/llvm/llvmjit.py ============================================================================== --- pypy/dist/pypy/jit/codegen/llvm/llvmjit.py (original) +++ pypy/dist/pypy/jit/codegen/llvm/llvmjit.py Fri Dec 1 17:30:13 2006 @@ -55,9 +55,13 @@ parse.restype = c_int parse.argtypes = [c_char_p] -find_function = llvmjit.find_function -find_function.restype = c_void_p -find_function.argtypes = [c_char_p] +getNamedFunction = llvmjit.getNamedFunction +getNamedFunction.restype = c_void_p +getNamedFunction.argtypes = [c_char_p] + +getNamedGlobal = llvmjit.getNamedGlobal +getNamedGlobal.restype = c_void_p +getNamedGlobal.argtypes = [c_char_p] freeMachineCodeForFunction = llvmjit.freeMachineCodeForFunction freeMachineCodeForFunction.restype = c_int @@ -71,17 +75,21 @@ execute.restype = c_int execute.argtypes = [c_void_p, c_int] -get_global_data= llvmjit.get_global_data +get_global_data = llvmjit.get_global_data get_global_data.restype = c_int get_global_data.argtypes = [] -set_global_data= llvmjit.set_global_data +set_global_data = llvmjit.set_global_data set_global_data.argtypes = [c_int] -get_pointer_to_global_data= llvmjit.get_pointer_to_global_data +get_pointer_to_global_data = llvmjit.get_pointer_to_global_data get_pointer_to_global_data.restype = POINTER(c_int) get_pointer_to_global_data.argtypes = [] -add_global_mapping = llvmjit.add_global_mapping -add_global_mapping.argtypes = [c_char_p, c_void_p] +get_pointer_to_global_function = llvmjit.get_pointer_to_global_function +get_pointer_to_global_function.restype = c_void_p +get_pointer_to_global_function.argtypes = [] + +addGlobalMapping = llvmjit.addGlobalMapping +addGlobalMapping.argtypes = [c_void_p, c_void_p] Modified: pypy/dist/pypy/jit/codegen/llvm/test/test_llvmjit.py ============================================================================== --- pypy/dist/pypy/jit/codegen/llvm/test/test_llvmjit.py (original) +++ pypy/dist/pypy/jit/codegen/llvm/test/test_llvmjit.py Fri Dec 1 17:30:13 2006 @@ -90,10 +90,20 @@ ret int %v2 }''' +# +llcall_global_function = '''declare int %my_global_function(int, int, int) + +implementation + +int %call_global_function(int %n) { + %v = call int %my_global_function(int 3, int %n, int 7) ;note: maybe tail call? + ret int %v +}''' + #helpers def execute(llsource, function_name, param): assert llvmjit.parse(llsource) - function = llvmjit.find_function(function_name) + function = llvmjit.getNamedFunction(function_name) assert function return llvmjit.execute(function, param) @@ -101,18 +111,18 @@ def test_restart(): for i in range(3): llvmjit.restart() - assert not llvmjit.find_function('square') + assert not llvmjit.getNamedFunction('square') assert llvmjit.parse(llsquare) - assert llvmjit.find_function('square') + assert llvmjit.getNamedFunction('square') -def test_find_function(): +def test_getNamedFunction(): for i in range(3): llvmjit.restart() - assert not llvmjit.find_function('square') - assert not llvmjit.find_function('square') + assert not llvmjit.getNamedFunction('square') + assert not llvmjit.getNamedFunction('square') assert llvmjit.parse(llsquare) - assert llvmjit.find_function('square') - assert llvmjit.find_function('square') + assert llvmjit.getNamedFunction('square') + assert llvmjit.getNamedFunction('square') def test_parse(): llvmjit.restart() @@ -130,8 +140,8 @@ llvmjit.restart() llvmjit.parse(llsquare) llvmjit.parse(llmul2) - square = llvmjit.find_function('square') - mul2 = llvmjit.find_function('mul2') + square = llvmjit.getNamedFunction('square') + mul2 = llvmjit.getNamedFunction('mul2') for i in range(5): assert llvmjit.execute(square, i) == i * i assert llvmjit.execute(mul2 , i) == i * 2 @@ -152,8 +162,8 @@ llvmjit.restart() llvmjit.parse(llacross1) llvmjit.parse(llacross2) - across1to2 = llvmjit.find_function('across1to2') - across2to1 = llvmjit.find_function('across2to1') + across1to2 = llvmjit.getNamedFunction('across1to2') + across2to1 = llvmjit.getNamedFunction('across2to1') for i in range(5): assert llvmjit.execute(across1to2, i) == my_across1to2(i) assert llvmjit.execute(across2to1, i) == my_across2to1(i) @@ -168,13 +178,13 @@ return n * n llvmjit.restart() llvmjit.parse(llfuncA) - _llfuncA = llvmjit.find_function('func') + _llfuncA = llvmjit.getNamedFunction('func') print '_llfuncA', _llfuncA for i in range(5): assert llvmjit.execute(_llfuncA, i) == funcA(i) llvmjit.freeMachineCodeForFunction(_llfuncA) llvmjit.parse(llfuncB) - _llfuncB = llvmjit.find_function('func') + _llfuncB = llvmjit.getNamedFunction('func') print '_llfuncB', _llfuncB llvmjit.recompile(_llfuncB) #note: because %func has changed because of the 2nd parse for i in range(5): @@ -183,7 +193,7 @@ def test_transform(): #XXX This uses Module transforms, think about Function transforms too. llvmjit.restart() llvmjit.parse(lldeadcode) - deadcode = llvmjit.find_function('deadcode') + deadcode = llvmjit.getNamedFunction('deadcode') assert llvmjit.execute(deadcode, 10) == 10 * 2 #XXX enable this part of the test asap @@ -199,16 +209,26 @@ assert llvmjit.get_global_data() == 10 gp_data = llvmjit.get_pointer_to_global_data() llvmjit.parse(llglobalmul4) - llvmjit.add_global_mapping('my_global_data', gp_data) #note: should be prior to execute() - globalmul4 = llvmjit.find_function('globalmul4') + p = llvmjit.getNamedGlobal('my_global_data...') + assert not p + p = llvmjit.getNamedGlobal('my_global_data') + assert p + llvmjit.addGlobalMapping(p, gp_data) #note: should be prior to execute() + globalmul4 = llvmjit.getNamedFunction('globalmul4') assert llvmjit.execute(globalmul4, 5) == 10 * 4 + 5 assert llvmjit.get_global_data() == 10 * 4 + 5 -def DONTtest_call_back_to_parent(): #call JIT-compiler again for it to add case(s) to flexswitch - pass - -def DONTtest_delete_function(): - pass +def test_call_global_function(): #used by PyPy JIT for adding case(s) to a flexswitch + llvmjit.restart() + gp_function = llvmjit.get_pointer_to_global_function() + llvmjit.parse(llcall_global_function) + p = llvmjit.getNamedFunction('my_global_function...') + assert not p + p = llvmjit.getNamedFunction('my_global_function') + assert p + llvmjit.addGlobalMapping(p, gp_function) #prior to execute()! + call_global_function = llvmjit.getNamedFunction('call_global_function') + assert llvmjit.execute(call_global_function, 5) == 3 + 5 + 7 def DONTtest_functions_with_different_signatures(): pass From fijal at codespeak.net Fri Dec 1 17:41:50 2006 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 1 Dec 2006 17:41:50 +0100 (CET) Subject: [pypy-svn] r35206 - pypy/dist/pypy/translator/c/test Message-ID: <20061201164150.A48D51007A@code0.codespeak.net> Author: fijal Date: Fri Dec 1 17:41:48 2006 New Revision: 35206 Modified: pypy/dist/pypy/translator/c/test/test_extfunc.py Log: Make function different (at least it annotates) Modified: pypy/dist/pypy/translator/c/test/test_extfunc.py ============================================================================== --- pypy/dist/pypy/translator/c/test/test_extfunc.py (original) +++ pypy/dist/pypy/translator/c/test/test_extfunc.py Fri Dec 1 17:41:48 2006 @@ -690,9 +690,10 @@ filename = str(udir.join('test_execv.txt')) def does_stuff(): progname = str(sys.executable) - l = [] - l.append(progname) - l += ["-c", 'open("%s","w").write("1")' % filename] + l = ['', ''] + l[0] = progname + l[1] = "-c" + l.append('open("%s","w").write("1")' % filename) pid = os.fork() if pid == 0: os.execv(progname, l) From arigo at codespeak.net Fri Dec 1 17:49:06 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 1 Dec 2006 17:49:06 +0100 (CET) Subject: [pypy-svn] r35207 - pypy/dist/pypy/rpython/rctypes Message-ID: <20061201164906.78D581007A@code0.codespeak.net> Author: arigo Date: Fri Dec 1 17:49:02 2006 New Revision: 35207 Modified: pypy/dist/pypy/rpython/rctypes/implementation.py Log: (ericvrp, arigo) We depend on ctypes' memory management details quite a lot nowadays, and versions before 0.9.9.6 didn't get it all right. Using them causes obscure segfaults, so better complain cleanly... Modified: pypy/dist/pypy/rpython/rctypes/implementation.py ============================================================================== --- pypy/dist/pypy/rpython/rctypes/implementation.py (original) +++ pypy/dist/pypy/rpython/rctypes/implementation.py Fri Dec 1 17:49:02 2006 @@ -3,6 +3,11 @@ from pypy.rpython import extregistry from pypy.rpython.extregistry import ExtRegistryEntry +import ctypes +if ctypes.__version__ < '0.9.9.6': # string comparison... good enough? + raise ImportError("requires ctypes >= 0.9.9.6, got %s" % ( + ctypes.__version__,)) + # rctypes version of ctypes.CFUNCTYPE. # It's required to work around three limitations of CFUNCTYPE: # From mwh at codespeak.net Fri Dec 1 18:05:05 2006 From: mwh at codespeak.net (mwh at codespeak.net) Date: Fri, 1 Dec 2006 18:05:05 +0100 (CET) Subject: [pypy-svn] r35208 - pypy/dist/pypy/jit/codegen/ppc Message-ID: <20061201170505.5D2E21006E@code0.codespeak.net> Author: mwh Date: Fri Dec 1 18:05:03 2006 New Revision: 35208 Modified: pypy/dist/pypy/jit/codegen/ppc/rgenop.py Log: trivial fix Modified: pypy/dist/pypy/jit/codegen/ppc/rgenop.py ============================================================================== --- pypy/dist/pypy/jit/codegen/ppc/rgenop.py (original) +++ pypy/dist/pypy/jit/codegen/ppc/rgenop.py Fri Dec 1 18:05:03 2006 @@ -686,7 +686,7 @@ # ---------------------------------------------------------------- # the public RGenOp interface - def newgraph(self, sigtoken): + def newgraph(self, sigtoken, name): numargs = sigtoken # for now builder = self.openbuilder() entrypoint = builder.asm.mc.tell() From arigo at codespeak.net Sun Dec 3 20:18:06 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 3 Dec 2006 20:18:06 +0100 (CET) Subject: [pypy-svn] r35224 - in pypy/branch/jit-real-world/pypy/jit/codegen/i386: . test Message-ID: <20061203191806.55A341005A@code0.codespeak.net> Author: arigo Date: Sun Dec 3 20:18:03 2006 New Revision: 35224 Modified: pypy/branch/jit-real-world/pypy/jit/codegen/i386/ri386setup.py pypy/branch/jit-real-world/pypy/jit/codegen/i386/test/test_operation.py Log: (pedronis, arigo) Added missing encoding for LEA. Changed the multimethd installer version used around here so that tests show the problem -- not just fully-compiled pypy-c's :-( Modified: pypy/branch/jit-real-world/pypy/jit/codegen/i386/ri386setup.py ============================================================================== --- pypy/branch/jit-real-world/pypy/jit/codegen/i386/ri386setup.py (original) +++ pypy/branch/jit-real-world/pypy/jit/codegen/i386/ri386setup.py Sun Dec 3 20:18:03 2006 @@ -5,7 +5,7 @@ """ from ri386 import * -from pypy.objspace.std.multimethod import MultiMethodTable +from pypy.objspace.std.multimethod import MultiMethodTable, InstallerVersion2 from pypy.tool.sourcetools import compile2 def reg2modrm(builder, reg): @@ -193,7 +193,11 @@ assert issubclass(cls, OPERAND) encoder1 = generate_function(sig, opcodes) table.register(encoder1, *sig) - encoder = table.install('__encode' + name, [type_order] * arity) + # always use the InstallerVersion2, including for testing, + # because it produces code that is more sensitive to + # registration errors + encoder = table.install('__encode' + name, [type_order] * arity, + installercls = InstallerVersion2) mmmin = min([len(mm) for mm in self.modes]) if mmmin < arity: encoder.func_defaults = (missing,) * (arity - mmmin) @@ -384,10 +388,10 @@ XCHG.mode2(REG8, MODRM8, ['\x86', register(1,8,'b'), modrm(2,'b')]) LEA = Instruction() -LEA.mode2(REG, MODRM, ['\x8D', register(1,8), modrm(2)]) -#for key in LEA.encodings.keys(): -# if key[1] != MODRM: -# del LEA.encodings[key] +LEA.mode2(REG, MODRM, ['\x8D', register(1,8), modrm(2)]) +LEA.mode2(REG, MODRM8, ['\x8D', register(1,8), modrm(2)]) +# some cases produce a MODRM8, but the result is always a 32-bit REG +# and the encoding is the same SHL = Instruction() SHL.mode2(MODRM, IMM8, ['\xC1', orbyte(4<<3), modrm(1), immediate(2,'b')]) Modified: pypy/branch/jit-real-world/pypy/jit/codegen/i386/test/test_operation.py ============================================================================== --- pypy/branch/jit-real-world/pypy/jit/codegen/i386/test/test_operation.py (original) +++ pypy/branch/jit-real-world/pypy/jit/codegen/i386/test/test_operation.py Sun Dec 3 20:18:03 2006 @@ -148,6 +148,19 @@ for i in range(5): assert fp(i) == fn(i) + def test_char_varsize_array(self): + A = lltype.GcArray(lltype.Char) + def fn(n): + a = lltype.malloc(A, n) + a[4] = 'H' + a[3] = 'e' + a[2] = 'l' + a[1] = 'l' + a[0] = 'o' + return ord(a[n-1]) + fp = self.rgen(fn, [int]) + assert fp(5) == fn(5) + def test_unichar_array(self): A = lltype.GcArray(lltype.UniChar) def fn(n): From fijal at codespeak.net Sun Dec 3 20:35:43 2006 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 3 Dec 2006 20:35:43 +0100 (CET) Subject: [pypy-svn] r35225 - in pypy/dist/pypy/module/posix: . test Message-ID: <20061203193543.7ED5110069@code0.codespeak.net> Author: fijal Date: Sun Dec 3 20:35:39 2006 New Revision: 35225 Modified: pypy/dist/pypy/module/posix/__init__.py pypy/dist/pypy/module/posix/interp_posix.py pypy/dist/pypy/module/posix/test/test_posix2.py Log: Added execve (module level) and test for it. Modified: pypy/dist/pypy/module/posix/__init__.py ============================================================================== --- pypy/dist/pypy/module/posix/__init__.py (original) +++ pypy/dist/pypy/module/posix/__init__.py Sun Dec 3 20:35:39 2006 @@ -72,6 +72,8 @@ interpleveldefs['waitpid'] = 'interp_posix.waitpid' if hasattr(os, 'execv'): interpleveldefs['execv'] = 'interp_posix.execv' + if hasattr(os, 'execve'): + interpleveldefs['execve'] = 'interp_posix.execve' #if hasattr(ctypes_posix, 'uname'): # interpleveldefs['uname'] = 'interp_posix.uname' 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 Dec 3 20:35:39 2006 @@ -399,9 +399,27 @@ geteuid.unwrap_spec = [ObjSpace] def execv(space, command, w_args): - os.execv(command, [space.str_w(i) for i in space.unpackiterable(w_args)]) + try: + os.execv(command, [space.str_w(i) for i in space.unpackiterable(w_args)]) + except OSError, e: + raise wrap_oserror(space, e) execv.unwrap_spec = [ObjSpace, str, W_Root] +def execve(space, command, w_args, w_env): + try: + args = [space.str_w(i) for i in space.unpackiterable(w_args)] + env = {} + keys = space.call_function(space.getattr(w_env, space.wrap('keys'))) + for key in space.unpackiterable(keys): + value = space.getitem(w_env, key) + env[space.str_w(key)] = space.str_w(value) + os.execve(command, args, env) + except ValueError, e: + raise OperationError(space.w_ValueError, space.wrap(str(e))) + except OSError, e: + raise wrap_oserror(space, e) +execve.unwrap_spec = [ObjSpace, str, W_Root, W_Root] + def uname(space): try: result = _c.uname() Modified: pypy/dist/pypy/module/posix/test/test_posix2.py ============================================================================== --- pypy/dist/pypy/module/posix/test/test_posix2.py (original) +++ pypy/dist/pypy/module/posix/test/test_posix2.py Sun Dec 3 20:35:39 2006 @@ -110,6 +110,26 @@ os.waitpid(pid, 0) assert open("onefile").read() == "1" os.unlink("onefile") + + def test_execv_raising(self): + os = self.posix + raises(OSError, 'os.execv("saddsadsadsadsa", ["saddsadsasaddsa"])') + + def test_execve(self): + os = self.posix + pid = os.fork() + if pid == 0: + os.execve("/usr/bin/env", ["env", "python", "-c", "import os; open('onefile', 'w').write(os.environ['ddd'])"], {'ddd':'xxx'}) + os.waitpid(pid, 0) + assert open("onefile").read() == "xxx" + os.unlink("onefile") + + if hasattr(__import__(os.name), 'popen'): + def test_popen(self): + skip("Not implemented") + os = self.posix + stream = os.popen('echo 1') + assert stream.read() == '1\n' class AppTestEnvironment(object): def setup_class(cls): From fijal at codespeak.net Sun Dec 3 20:39:43 2006 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 3 Dec 2006 20:39:43 +0100 (CET) Subject: [pypy-svn] r35226 - in pypy/dist/pypy: rpython rpython/module translator/c translator/c/src translator/c/test Message-ID: <20061203193943.11B4410069@code0.codespeak.net> Author: fijal Date: Sun Dec 3 20:39:32 2006 New Revision: 35226 Modified: pypy/dist/pypy/rpython/extfunctable.py pypy/dist/pypy/rpython/module/ll_os.py pypy/dist/pypy/rpython/module/support.py pypy/dist/pypy/translator/c/extfunc.py pypy/dist/pypy/translator/c/src/ll_os.h pypy/dist/pypy/translator/c/test/test_extfunc.py Log: implemented os.execve and added some mess to rpython/module/support.py. It really need new attempt of doing stuff (to kill all the crap which is not run, but only annotated and still causes problems). Modified: pypy/dist/pypy/rpython/extfunctable.py ============================================================================== --- pypy/dist/pypy/rpython/extfunctable.py (original) +++ pypy/dist/pypy/rpython/extfunctable.py Sun Dec 3 20:39:32 2006 @@ -235,6 +235,7 @@ declare(os.waitpid , waitpidannotation, 'll_os/waitpid') if hasattr(os, 'execv'): declare(os.execv, noneannotation, 'll_os/execv') + declare(os.execve, noneannotation, 'll_os/execve') declare(os.path.exists, bool , 'll_os_path/exists') declare(os.path.isdir, bool , 'll_os_path/isdir') 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 Sun Dec 3 20:39:32 2006 @@ -14,7 +14,8 @@ # and buffer preparation stuff is not useful. import os, errno -from pypy.rpython.module.support import ll_strcpy, _ll_strfill +from pypy.rpython.module.support import ll_strcpy, _ll_strfill, ll_execve, \ + from_rdict from pypy.rpython.module.support import to_opaque_object, from_opaque_object from pypy.rlib import ros from pypy.rlib.rarithmetic import r_longlong @@ -100,6 +101,10 @@ os.execv(cmd, args) ll_os_execv.suggested_primitive = True + def ll_os_execve(cls, cmd, args, env): + env_list = from_rdict(env) + ll_execve(cmd, args, env_list) + def ll_os_unlink(cls, path): os.unlink(cls.from_rstr(path)) ll_os_unlink.suggested_primitive = True Modified: pypy/dist/pypy/rpython/module/support.py ============================================================================== --- pypy/dist/pypy/rpython/module/support.py (original) +++ pypy/dist/pypy/rpython/module/support.py Sun Dec 3 20:39:32 2006 @@ -2,10 +2,30 @@ from pypy.rpython.ootypesystem import ootype from pypy.rpython import extfunctable from pypy.rpython.lltypesystem.lltype import \ - GcStruct, Signed, Array, Char, Ptr, malloc + GcStruct, Signed, Array, Char, Ptr, malloc, GcArray +from pypy.rpython.rlist import ll_append +from pypy.rpython.lltypesystem.rlist import ll_newlist, ListRepr,\ + ll_getitem_fast +from pypy.rpython.lltypesystem.rstr import string_repr +from pypy.rpython.lltypesystem.rdict import ll_newdict, DictRepr, dum_items,\ + ll_kvi, dum_keys, ll_dict_getitem, ll_dict_setitem +from pypy.rpython.lltypesystem.rstr import StringRepr +from pypy.rpython.lltypesystem.rtuple import TupleRepr +from pypy.annotation.dictdef import DictKey, DictValue +from pypy.annotation.model import SomeString +import os + +# This whole mess is just to make annotator happy... +list_repr = ListRepr(None, string_repr) +list_repr.setup() +LIST = list_repr.lowleveltype.TO +tuple_repr = TupleRepr(None, [string_repr, string_repr]) +tuple_repr.setup() +tuple_list_repr = ListRepr(None, tuple_repr) +tuple_list_repr.setup() +LIST_TUPLE = tuple_list_repr.lowleveltype.TO # utility conversion functions - class LLSupport: _mixin_ = True @@ -17,7 +37,7 @@ for i in range(len(s)): p.chars[i] = s[i] return p - to_rstr = staticmethod(to_rstr) + to_rstr = staticmethod(to_rstr) def from_rstr(rs): if not rs: # null pointer @@ -26,6 +46,31 @@ return ''.join([rs.chars[i] for i in range(len(rs.chars))]) from_rstr = staticmethod(from_rstr) +def from_rdict(rs): + ritems = ll_kvi(rs, LIST_TUPLE, dum_items) + res = ll_newlist(LIST, 0) + index = 0 + while index < ritems.ll_length(): + ritem = ll_getitem_fast(ritems, index) + ll_append(res, LLSupport.to_rstr("%s=%s" % (LLSupport.from_rstr(ritem.item0), + LLSupport.from_rstr(ritem.item1)))) + index += 1 + return res + +def to_rdict(rs): + d = {} + index = 0 + while index < rs.ll_length(): + item = LLSupport.from_rstr(ll_getitem_fast(rs, index)) + key, value = item.split("=") + d[key] = value + index += 1 + return d + +def ll_execve(cmd, args, env_list): + env = to_rdict(env_list) + os.execve(cmd, args, env) +ll_execve.suggested_primitive = True class OOSupport: _mixin_ = True Modified: pypy/dist/pypy/translator/c/extfunc.py ============================================================================== --- pypy/dist/pypy/translator/c/extfunc.py (original) +++ pypy/dist/pypy/translator/c/extfunc.py Sun Dec 3 20:39:32 2006 @@ -7,11 +7,13 @@ from pypy.rpython.lltypesystem import rlist from pypy.rpython.module import ll_time, ll_math, ll_strtod from pypy.rpython.module import ll_stackless, ll_stack +from pypy.rpython.module.support import ll_execve from pypy.rpython.lltypesystem.module.ll_os import STAT_RESULT, PIPE_RESULT from pypy.rpython.lltypesystem.module.ll_os import WAITPID_RESULT from pypy.rpython.lltypesystem.module.ll_os import Implementation as impl from pypy.rpython.lltypesystem.module import ll_math as ll_math2 from pypy.rpython.lltypesystem.module import ll_strtod as ll_strtod2 +from pypy.rlib import ros try: from pypy.module.thread.rpython import ll_thread @@ -61,6 +63,7 @@ impl.ll_os_waitpid.im_func: 'LL_os_waitpid', impl.ll_os__exit.im_func: 'LL_os__exit', impl.ll_os_execv.im_func: 'LL_os_execv', + ll_execve: 'LL_os_execve', ll_time.ll_time_clock: 'LL_time_clock', ll_time.ll_time_sleep: 'LL_time_sleep', ll_time.ll_time_time: 'LL_time_time', Modified: pypy/dist/pypy/translator/c/src/ll_os.h ============================================================================== --- pypy/dist/pypy/translator/c/src/ll_os.h (original) +++ pypy/dist/pypy/translator/c/src/ll_os.h Sun Dec 3 20:39:32 2006 @@ -80,7 +80,10 @@ long LL_readlink_into(RPyString *path, RPyString *buffer); long LL_os_fork(void); #ifdef HAVE_RPY_LIST_OF_STRING /* argh */ +#ifdef HAVE_EXECV void LL_os_execv(RPyString *cmd, RPyListOfString *args); +void LL_os_execve(RPyString *cmd, RPyListOfString *args, RPyListOfString *env); +#endif long LL_os_spawnv(int mode, RPyString *path, RPyListOfString *args); #endif RPyWAITPID_RESULT* LL_os_waitpid(long pid, long options); @@ -391,15 +394,34 @@ #endif #if defined(HAVE_EXECV) && defined(HAVE_RPY_LIST_OF_STRING) -void LL_os_execv(RPyString *cmd, RPyListOfString *args) { +char** get_slist(RPyListOfString *args) +{ int i, nargs = args->l_length; char **slist = malloc((nargs+1) * sizeof(char*)); if (slist) { for (i=0; il_items->items[i]); slist[nargs] = NULL; - execv(RPyString_AsString(cmd), slist); - } /* should never return */ + return slist; + } else { + RPYTHON_RAISE_OSERROR(errno); + return NULL; + } +} + +void LL_os_execv(RPyString *cmd, RPyListOfString *args) { + char **slist = get_slist(args); + execv(RPyString_AsString(cmd), slist); + /* should never return */ + RPYTHON_RAISE_OSERROR(errno); +} + +void LL_os_execve(RPyString *cmd, RPyListOfString *args, RPyListOfString *env) +{ + char **arglist = get_slist(args); + char **envlist = get_slist(env); + execve(RPyString_AsString(cmd), arglist, envlist); + /* should never return */ RPYTHON_RAISE_OSERROR(errno); } #endif Modified: pypy/dist/pypy/translator/c/test/test_extfunc.py ============================================================================== --- pypy/dist/pypy/translator/c/test/test_extfunc.py (original) +++ pypy/dist/pypy/translator/c/test/test_extfunc.py Sun Dec 3 20:39:32 2006 @@ -5,7 +5,6 @@ from pypy.translator.c.test.test_genc import compile from pypy.translator.c.extfunc import EXTERNALS from pypy.rlib import ros -from pypy.translator.stackless.test.test_transform import one def test_all_suggested_primitives(): for modulename in ['ll_math', 'll_os', 'll_os_path', 'll_time']: @@ -703,3 +702,33 @@ func() assert open(filename).read() == "1" + def test_execv_raising(): + def does_stuff(): + l = [] + l.append("asddsadw32eewdfwqdqwdqwd") + os.execv(l[0], l) + + func = compile(does_stuff, []) + py.test.raises(OSError, "func()") + + def test_execve(): + filename = str(udir.join('test_execve.txt')) + def does_stuff(): + progname = str(sys.executable) + l = [] + l.append(progname) + l.append("-c") + l.append('import os; open("%s", "w").write(os.environ["STH"])' % filename) + env = {} + env["STH"] = "42" + env["sthelse"] = "a" + pid = os.fork() + if pid == 0: + os.execve(progname, l, env) + else: + os.waitpid(pid, 0) + + func = compile(does_stuff, []) + func() + assert open(filename).read() == "42" + From fijal at codespeak.net Sun Dec 3 20:49:49 2006 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 3 Dec 2006 20:49:49 +0100 (CET) Subject: [pypy-svn] r35227 - pypy/dist/pypy/translator/goal Message-ID: <20061203194949.5C55510069@code0.codespeak.net> Author: fijal Date: Sun Dec 3 20:49:47 2006 New Revision: 35227 Modified: pypy/dist/pypy/translator/goal/app_main.py Log: Fix the check. Modified: pypy/dist/pypy/translator/goal/app_main.py ============================================================================== --- pypy/dist/pypy/translator/goal/app_main.py (original) +++ pypy/dist/pypy/translator/goal/app_main.py Sun Dec 3 20:49:47 2006 @@ -180,7 +180,7 @@ if arg == '-i': go_interactive = True elif arg == '-c': - if i >= len(argv)-1: + if i >= len(argv): print_error('Argument expected for the -c option') return 2 break From fijal at codespeak.net Sun Dec 3 22:32:14 2006 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 3 Dec 2006 22:32:14 +0100 (CET) Subject: [pypy-svn] r35228 - pypy/dist/pypy/translator/goal Message-ID: <20061203213214.16D2A10069@code0.codespeak.net> Author: fijal Date: Sun Dec 3 22:32:12 2006 New Revision: 35228 Modified: pypy/dist/pypy/translator/goal/app_main.py Log: Fix a bit app_main, -c should work now Modified: pypy/dist/pypy/translator/goal/app_main.py ============================================================================== --- pypy/dist/pypy/translator/goal/app_main.py (original) +++ pypy/dist/pypy/translator/goal/app_main.py Sun Dec 3 22:32:12 2006 @@ -176,7 +176,6 @@ arg = argv[i] if not arg.startswith('-'): break - i += 1 if arg == '-i': go_interactive = True elif arg == '-c': @@ -198,10 +197,12 @@ print_help() return 0 elif arg == '--': + i += 1 break # terminates option list else: print_error('unrecognized option %r' % (arg,)) return 2 + i += 1 sys.argv = argv[i:] # with PyPy in top of CPython we can only have around 100 From arigo at codespeak.net Sun Dec 3 22:48:12 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 3 Dec 2006 22:48:12 +0100 (CET) Subject: [pypy-svn] r35229 - pypy/dist/pypy/translator/goal Message-ID: <20061203214812.0DE1410064@code0.codespeak.net> Author: arigo Date: Sun Dec 3 22:48:10 2006 New Revision: 35229 Modified: pypy/dist/pypy/translator/goal/app_main.py Log: Fix app_main more, for the case "python -- -c". Modified: pypy/dist/pypy/translator/goal/app_main.py ============================================================================== --- pypy/dist/pypy/translator/goal/app_main.py (original) +++ pypy/dist/pypy/translator/goal/app_main.py Sun Dec 3 22:48:10 2006 @@ -171,6 +171,7 @@ break go_interactive = False + run_command = False i = 0 while i < len(argv): arg = argv[i] @@ -182,6 +183,7 @@ if i >= len(argv): print_error('Argument expected for the -c option') return 2 + run_command = True break elif arg == '-u': set_unbuffered_io() @@ -226,7 +228,7 @@ try: if sys.argv: - if sys.argv[0] == '-c': + if run_command: cmd = sys.argv.pop(1) def run_it(): exec cmd in mainmodule.__dict__ From arigo at codespeak.net Sun Dec 3 23:16:44 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 3 Dec 2006 23:16:44 +0100 (CET) Subject: [pypy-svn] r35230 - pypy/branch/jit-real-world/pypy/objspace/std Message-ID: <20061203221644.8E5C010072@code0.codespeak.net> Author: arigo Date: Sun Dec 3 23:16:40 2006 New Revision: 35230 Modified: pypy/branch/jit-real-world/pypy/objspace/std/multimethod.py Log: Forgot to check this in with r35224. Modified: pypy/branch/jit-real-world/pypy/objspace/std/multimethod.py ============================================================================== --- pypy/branch/jit-real-world/pypy/objspace/std/multimethod.py (original) +++ pypy/branch/jit-real-world/pypy/objspace/std/multimethod.py Sun Dec 3 23:16:40 2006 @@ -40,20 +40,22 @@ lst[order] = function def install(self, prefix, list_of_typeorders, baked_perform_call=True, - base_typeorder=None): + base_typeorder=None, installercls=None): "NOT_RPYTHON: initialization-time only" assert len(list_of_typeorders) == self.arity - installer = Installer(self, prefix, list_of_typeorders, - baked_perform_call=baked_perform_call, - base_typeorder=base_typeorder) + installercls = installercls or Installer + installer = installercls(self, prefix, list_of_typeorders, + baked_perform_call=baked_perform_call, + base_typeorder=base_typeorder) return installer.install() def install_if_not_empty(self, prefix, list_of_typeorders, - base_typeorder=None): + base_typeorder=None, installercls=None): "NOT_RPYTHON: initialization-time only" assert len(list_of_typeorders) == self.arity - installer = Installer(self, prefix, list_of_typeorders, - base_typeorder=base_typeorder) + installercls = installercls or Installer + installer = installercls(self, prefix, list_of_typeorders, + base_typeorder=base_typeorder) if installer.is_empty(): return None else: From arigo at codespeak.net Sun Dec 3 23:17:55 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 3 Dec 2006 23:17:55 +0100 (CET) Subject: [pypy-svn] r35231 - pypy/branch/jit-real-world/pypy/translator/goal Message-ID: <20061203221755.DF61710070@code0.codespeak.net> Author: arigo Date: Sun Dec 3 23:17:54 2006 New Revision: 35231 Modified: pypy/branch/jit-real-world/pypy/translator/goal/unixcheckpoint.py Log: Make the 'pdb' command of --fork-before not crash when pdb receives a Ctrl-D. Modified: pypy/branch/jit-real-world/pypy/translator/goal/unixcheckpoint.py ============================================================================== --- pypy/branch/jit-real-world/pypy/translator/goal/unixcheckpoint.py (original) +++ pypy/branch/jit-real-world/pypy/translator/goal/unixcheckpoint.py Sun Dec 3 23:17:54 2006 @@ -25,7 +25,12 @@ if line == 'quit': raise SystemExit if line == 'pdb': - import pdb; pdb.set_trace() + try: + import pdb; pdb.set_trace() + dummy_for_pdb = 1 # for pdb to land + except Exception, e: + print '(%s ignored)' % e.__class__.__name__ + continue if line == 'restart': restart_process() From arigo at codespeak.net Sun Dec 3 23:18:39 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 3 Dec 2006 23:18:39 +0100 (CET) Subject: [pypy-svn] r35232 - pypy/branch/jit-real-world/pypy/tool Message-ID: <20061203221839.9039B10071@code0.codespeak.net> Author: arigo Date: Sun Dec 3 23:18:38 2006 New Revision: 35232 Modified: pypy/branch/jit-real-world/pypy/tool/error.py Log: Even without debugging info, blocked blocks can display meaningful errors because the blocked operation is the first one whose result is not annotated. Modified: pypy/branch/jit-real-world/pypy/tool/error.py ============================================================================== --- pypy/branch/jit-real-world/pypy/tool/error.py (original) +++ pypy/branch/jit-real-world/pypy/tool/error.py Sun Dec 3 23:18:38 2006 @@ -71,16 +71,26 @@ msg = [""] msg.append('-+' * 30) from pypy.annotation import model + msg.append("Blocked block -- operation cannot succeed") if model.DEBUG: - msg.append("Blocked block -- operation cannot succeed") _, _, operindex = annotator.why_not_annotated[block][1].break_at + else: + # guess the blocked operation by the fact that its return value is + # not annotated + for operindex in range(len(block.operations)): + if block.operations[operindex].result not in annotator.bindings: + break + else: + operindex = None + + if operindex is not None: oper = block.operations[operindex] msg.append(" " + str(oper)) else: - msg.append("Blocked block") - operindex = None + oper = None + msg.append(" (inconsistency - the block is fully annotated??)") msg += source_lines(graph, block, operindex, long=True) - if model.DEBUG: + if oper is not None: if SHOW_ANNOTATIONS: msg.append("Known variable annotations:") for arg in oper.args + [oper.result]: @@ -89,7 +99,7 @@ msg.append(" " + str(arg) + " = " + str(annotator.binding(arg))) except KeyError: pass - if SHOW_TRACEBACK: + if model.DEBUG and SHOW_TRACEBACK: msg.extend(traceback.format_exception(*annotator.why_not_annotated[block])) return "\n".join(msg) From arigo at codespeak.net Sun Dec 3 23:19:32 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 3 Dec 2006 23:19:32 +0100 (CET) Subject: [pypy-svn] r35233 - pypy/branch/jit-real-world/pypy/jit/goal Message-ID: <20061203221932.E88C810064@code0.codespeak.net> Author: arigo Date: Sun Dec 3 23:19:31 2006 New Revision: 35233 Modified: pypy/branch/jit-real-world/pypy/jit/goal/jitstep.py Log: Trying to compile a 386 version of the JIT in pypy-c. Modified: pypy/branch/jit-real-world/pypy/jit/goal/jitstep.py ============================================================================== --- pypy/branch/jit-real-world/pypy/jit/goal/jitstep.py (original) +++ pypy/branch/jit-real-world/pypy/jit/goal/jitstep.py Sun Dec 3 23:19:31 2006 @@ -1,5 +1,6 @@ from pypy.interpreter.pyframe import PyFrame +from pypy.objspace.flow.model import checkgraph from pypy.translator.translator import graphof from pypy.jit.hintannotator.annotator import HintAnnotator, HintAnnotatorPolicy from pypy.jit.hintannotator.model import OriginFlags, SomeLLAbstractConstant @@ -48,7 +49,9 @@ def timeshift(drv): from pypy.jit.timeshifter.hrtyper import HintRTyper - from pypy.jit.codegen.llgraph.rgenop import RGenOp # for now + #from pypy.jit.codegen.llgraph.rgenop import RGenOp + from pypy.jit.codegen.i386.rgenop import RI386GenOp as RGenOp + ha = drv.hannotator t = drv.translator # make the timeshifted graphs @@ -58,4 +61,6 @@ for graph in ha.translator.graphs: checkgraph(graph) t.graphs.append(graph) - import pdb; pdb.set_trace() + + # XXX temp + drv.compile() From arigo at codespeak.net Sun Dec 3 23:20:40 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 3 Dec 2006 23:20:40 +0100 (CET) Subject: [pypy-svn] r35234 - pypy/branch/jit-real-world/pypy/jit/timeshifter/test Message-ID: <20061203222040.7969210074@code0.codespeak.net> Author: arigo Date: Sun Dec 3 23:20:39 2006 New Revision: 35234 Modified: pypy/branch/jit-real-world/pypy/jit/timeshifter/test/test_timeshift.py pypy/branch/jit-real-world/pypy/jit/timeshifter/test/test_vdict.py Log: Fix an AnnotatorPolicy left behind. Add a test. Modified: pypy/branch/jit-real-world/pypy/jit/timeshifter/test/test_timeshift.py ============================================================================== --- pypy/branch/jit-real-world/pypy/jit/timeshifter/test/test_timeshift.py (original) +++ pypy/branch/jit-real-world/pypy/jit/timeshifter/test/test_timeshift.py Sun Dec 3 23:20:39 2006 @@ -14,7 +14,6 @@ from pypy.annotation import model as annmodel from pypy.rpython.llinterp import LLInterpreter, LLException from pypy.objspace.flow.model import checkgraph -from pypy.annotation.policy import AnnotatorPolicy from pypy.translator.backendopt.inline import auto_inlining from pypy import conftest from pypy.jit.conftest import Benchmark Modified: pypy/branch/jit-real-world/pypy/jit/timeshifter/test/test_vdict.py ============================================================================== --- pypy/branch/jit-real-world/pypy/jit/timeshifter/test/test_vdict.py (original) +++ pypy/branch/jit-real-world/pypy/jit/timeshifter/test/test_vdict.py Sun Dec 3 23:20:39 2006 @@ -1,9 +1,8 @@ -from pypy.annotation.policy import AnnotatorPolicy +from pypy.jit.hintannotator.annotator import HintAnnotatorPolicy from pypy.jit.timeshifter.test.test_timeshift import TimeshiftingTests -P_OOPSPEC = AnnotatorPolicy() -P_OOPSPEC.novirtualcontainer = True -P_OOPSPEC.oopspec = True +P_OOPSPEC = HintAnnotatorPolicy(novirtualcontainer = True, + oopspec = True) class TestVDict(TimeshiftingTests): @@ -28,3 +27,16 @@ res = self.timeshift(ll_function, [], [], policy=P_OOPSPEC) assert res == 34 self.check_insns({}) + + def test_multiple_vdicts(self): + def ll_function(): + d1 = {} + d1[12] = 34 + l1 = [12] + l2 = ['foo'] + d2 = {} + d2['foo'] = 'hello' + return d1[l1.pop()] + len(d2[l2.pop()]) + res = self.timeshift(ll_function, [], [], policy=P_OOPSPEC) + assert res == 39 + self.check_insns({}) From arigo at codespeak.net Sun Dec 3 23:23:10 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 3 Dec 2006 23:23:10 +0100 (CET) Subject: [pypy-svn] r35235 - in pypy/branch/jit-real-world/pypy/jit: codegen/i386 codegen/llgraph timeshifter Message-ID: <20061203222310.626DC10074@code0.codespeak.net> Author: arigo Date: Sun Dec 3 23:23:07 2006 New Revision: 35235 Modified: pypy/branch/jit-real-world/pypy/jit/codegen/i386/rgenop.py pypy/branch/jit-real-world/pypy/jit/codegen/llgraph/rgenop.py pypy/branch/jit-real-world/pypy/jit/timeshifter/hrtyper.py pypy/branch/jit-real-world/pypy/jit/timeshifter/transform.py Log: (pedronis, arigo) Change the policy for Void arguments in genop_call(). Now they are never present at all. The only back-end that cares is llgraph, which can hack them back. Modified: pypy/branch/jit-real-world/pypy/jit/codegen/i386/rgenop.py ============================================================================== --- pypy/branch/jit-real-world/pypy/jit/codegen/i386/rgenop.py (original) +++ pypy/branch/jit-real-world/pypy/jit/codegen/i386/rgenop.py Sun Dec 3 23:23:07 2006 @@ -346,20 +346,17 @@ return self.returnvar(eax) def genop_call(self, sigtoken, gv_fnptr, args_gv): + numargs = sigtoken # for now MASK = CALL_ALIGN-1 if MASK: - final_depth = self.stackdepth - for gv_arg in args_gv: - if gv_arg is not None: - final_depth += 1 + final_depth = self.stackdepth + numargs delta = (final_depth+MASK)&~MASK-final_depth if delta: self.mc.SUB(esp, imm(delta*WORD)) self.stackdepth += delta - for i in range(len(args_gv)-1, -1, -1): + for i in range(numargs-1, -1, -1): gv_arg = args_gv[i] - if gv_arg is not None: - self.push(gv_arg.operand(self)) + self.push(gv_arg.operand(self)) if gv_fnptr.is_const: target = gv_fnptr.revealconst(lltype.Signed) self.mc.CALL(rel32(target)) Modified: pypy/branch/jit-real-world/pypy/jit/codegen/llgraph/rgenop.py ============================================================================== --- pypy/branch/jit-real-world/pypy/jit/codegen/llgraph/rgenop.py (original) +++ pypy/branch/jit-real-world/pypy/jit/codegen/llgraph/rgenop.py Sun Dec 3 23:23:07 2006 @@ -25,7 +25,18 @@ def __repr__(self): return repr(RGenOp.reveal(self)) -gv_Void = LLConst(llimpl.constTYPE(lltype.Void)) + +_gv_TYPE_cache = {} +def gv_TYPE(TYPE): + try: + return _gv_TYPE_cache[TYPE] + except KeyError: + gv = LLConst(llimpl.constTYPE(TYPE)) + _gv_TYPE_cache[TYPE] = gv + return gv + +gv_Void = gv_TYPE(lltype.Void) +gv_Signed = gv_TYPE(lltype.Signed) gv_dummy_placeholder = LLConst(llimpl.dummy_placeholder) @@ -75,10 +86,13 @@ def genop_call(self, (ARGS_gv, gv_RESULT, _), gv_callable, args_gv): vars_gv = [gv_callable] + j = 0 for i in range(len(ARGS_gv)): - gv_arg = args_gv[i] - if gv_arg is not None: - gv_arg = LLVar(llimpl.cast(self.b, ARGS_gv[i].v, gv_arg.v)) + if ARGS_gv[i] is gv_Void: + gv_arg = gv_dummy_placeholder + else: + gv_arg = LLVar(llimpl.cast(self.b, ARGS_gv[i].v, args_gv[j])) + j += 1 vars_gv.append(gv_arg) if gv_callable.is_const: v = llimpl.genop(self.b, 'direct_call', vars_gv, gv_RESULT.v) @@ -122,7 +136,7 @@ def genop_getarraysize(self, gv_ITEMTYPE, gv_ptr): return LLVar(llimpl.genop(self.b, 'getarraysize', [gv_ptr.v], - llimpl.constTYPE(lltype.Signed))) + gv_Signed.v)) def genop_malloc_fixedsize(self, (gv_TYPE, gv_PTRTYPE)): vars_gv = [gv_TYPE.v] @@ -212,7 +226,7 @@ @staticmethod @specialize.memo() def kindToken(T): - return LLConst(llimpl.constTYPE(T)) + return gv_TYPE(T) @staticmethod @specialize.memo() @@ -222,14 +236,14 @@ if isinstance(FIELDTYPE, lltype.ContainerType): FIELDTYPE = lltype.Ptr(FIELDTYPE) return (LLConst(llimpl.constFieldName(name)), - LLConst(llimpl.constTYPE(lltype.Ptr(T))), - LLConst(llimpl.constTYPE(FIELDTYPE))) + gv_TYPE(lltype.Ptr(T)), + gv_TYPE(FIELDTYPE)) @staticmethod @specialize.memo() def allocToken(TYPE): - return (LLConst(llimpl.constTYPE(TYPE)), - LLConst(llimpl.constTYPE(lltype.Ptr(TYPE)))) + return (gv_TYPE(TYPE), + gv_TYPE(lltype.Ptr(TYPE))) varsizeAllocToken = allocToken @@ -239,14 +253,14 @@ ITEMTYPE = A.OF if isinstance(ITEMTYPE, lltype.ContainerType): ITEMTYPE = lltype.Ptr(ITEMTYPE) - return LLConst(llimpl.constTYPE(ITEMTYPE)) + return gv_TYPE(ITEMTYPE) @staticmethod @specialize.memo() def sigToken(FUNCTYPE): - return ([LLConst(llimpl.constTYPE(A)) for A in FUNCTYPE.ARGS], - LLConst(llimpl.constTYPE(FUNCTYPE.RESULT)), - LLConst(llimpl.constTYPE(FUNCTYPE))) + return ([gv_TYPE(A) for A in FUNCTYPE.ARGS], + gv_TYPE(FUNCTYPE.RESULT), + gv_TYPE(FUNCTYPE)) constPrebuiltGlobal = genconst Modified: pypy/branch/jit-real-world/pypy/jit/timeshifter/hrtyper.py ============================================================================== --- pypy/branch/jit-real-world/pypy/jit/timeshifter/hrtyper.py (original) +++ pypy/branch/jit-real-world/pypy/jit/timeshifter/hrtyper.py Sun Dec 3 23:23:07 2006 @@ -146,7 +146,7 @@ self.ll_finish_jitstate = ll_finish_jitstate self.v_queue = varoftype(self.r_Queue.lowleveltype, 'queue') - self.void_red_repr = VoidRedRepr(self) + #self.void_red_repr = VoidRedRepr(self) def specialize(self, origportalgraph=None, view=False): """ @@ -184,6 +184,7 @@ self.annotator.translator.view() # in the middle for graph in seen: self.timeshift_graph(graph) + self.log.event("Timeshifted %d graphs." % (len(seen),)) if origportalgraph: self.rewire_portal() @@ -490,11 +491,11 @@ self.red_reprs[lowleveltype] = r return r - def getredrepr_or_none(self, lowleveltype): - if lowleveltype is lltype.Void: - return self.void_red_repr - else: - return self.getredrepr(lowleveltype) +## def getredrepr_or_none(self, lowleveltype): +## if lowleveltype is lltype.Void: +## return self.void_red_repr +## else: +## return self.getredrepr(lowleveltype) ## def gethscolor(self, hs): ## try: @@ -613,7 +614,7 @@ hop.llops.append(hop.spaceop) return hop.spaceop.result else: - print "RED op", hop.spaceop + #print "RED op", hop.spaceop return None def default_translate_operation(self, hop): @@ -930,7 +931,7 @@ def translate_op_save_locals(self, hop): v_jitstate = hop.llops.getjitstate() - boxes_r = [self.getredrepr_or_none(originalconcretetype(hs)) + boxes_r = [self.getredrepr(originalconcretetype(hs)) for hs in hop.args_s] boxes_v = hop.inputargs(*boxes_r) boxes_s = [self.s_RedBox] * len(hop.args_v) @@ -1454,12 +1455,12 @@ return hop.llops.as_redbox(v_ptrbox) -class VoidRedRepr(Repr): - def __init__(self, hrtyper): - self.lowleveltype = hrtyper.r_RedBox.lowleveltype +##class VoidRedRepr(Repr): +## def __init__(self, hrtyper): +## self.lowleveltype = hrtyper.r_RedBox.lowleveltype - def convert_const(self, ll_value): - return lltype.nullptr(self.lowleveltype.TO) +## def convert_const(self, ll_value): +## return lltype.nullptr(self.lowleveltype.TO) class BlueRepr(Repr): Modified: pypy/branch/jit-real-world/pypy/jit/timeshifter/transform.py ============================================================================== --- pypy/branch/jit-real-world/pypy/jit/timeshifter/transform.py (original) +++ pypy/branch/jit-real-world/pypy/jit/timeshifter/transform.py Sun Dec 3 23:23:07 2006 @@ -576,6 +576,7 @@ if op.opname == 'indirect_call': del args_v[-1] # pseudo-obscure: the arguments for the call go in save_locals + args_v = [v for v in args_v if v.concretetype is not lltype.Void] self.genop(nonconstantblock, 'save_locals', args_v) v_res = self.genop(nonconstantblock, 'residual_%s_call' % (color,), [op.args[0]], result_like = op.result) @@ -665,6 +666,7 @@ color = 'red' newops = [] # pseudo-obscure: the arguments for the call go in save_locals + args_v = [v for v in args_v if v.concretetype is not lltype.Void] self.genop(newops, 'save_locals', args_v) self.genop(newops, 'residual_%s_call' % (color,), [op.args[0]], result_like = op.result) From arigo at codespeak.net Mon Dec 4 00:11:38 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 4 Dec 2006 00:11:38 +0100 (CET) Subject: [pypy-svn] r35237 - in pypy/branch/jit-real-world/pypy/jit: codegen/llgraph timeshifter Message-ID: <20061203231138.D4A0F10053@code0.codespeak.net> Author: arigo Date: Mon Dec 4 00:11:35 2006 New Revision: 35237 Modified: pypy/branch/jit-real-world/pypy/jit/codegen/llgraph/rgenop.py pypy/branch/jit-real-world/pypy/jit/timeshifter/oop.py pypy/branch/jit-real-world/pypy/jit/timeshifter/vdict.py pypy/branch/jit-real-world/pypy/jit/timeshifter/vlist.py Log: (pedronis, arigo) Bugs left behind by arigo in removing None arguments to genop_call(). Modified: pypy/branch/jit-real-world/pypy/jit/codegen/llgraph/rgenop.py ============================================================================== --- pypy/branch/jit-real-world/pypy/jit/codegen/llgraph/rgenop.py (original) +++ pypy/branch/jit-real-world/pypy/jit/codegen/llgraph/rgenop.py Mon Dec 4 00:11:35 2006 @@ -91,7 +91,7 @@ if ARGS_gv[i] is gv_Void: gv_arg = gv_dummy_placeholder else: - gv_arg = LLVar(llimpl.cast(self.b, ARGS_gv[i].v, args_gv[j])) + gv_arg = LLVar(llimpl.cast(self.b, ARGS_gv[i].v, args_gv[j].v)) j += 1 vars_gv.append(gv_arg) if gv_callable.is_const: Modified: pypy/branch/jit-real-world/pypy/jit/timeshifter/oop.py ============================================================================== --- pypy/branch/jit-real-world/pypy/jit/timeshifter/oop.py (original) +++ pypy/branch/jit-real-world/pypy/jit/timeshifter/oop.py Mon Dec 4 00:11:35 2006 @@ -32,16 +32,16 @@ self.argtuple = eval(args, d) # end of rather XXX'edly hackish parsing - self.argpositions = [] + arg_llsig_to_oopsig = {} for i, obj in enumerate(self.argtuple): if isinstance(obj, Index): - self.argpositions.append(obj.n) - else: - self.argpositions.append(-1) + arg_llsig_to_oopsig[obj.n] = i + self.residualargsources = [] for i in range(nb_args): ARGTYPE = FUNCTYPE.ARGS[i] - assert (i in self.argpositions) == (ARGTYPE is not lltype.Void) + if ARGTYPE is not lltype.Void: + self.residualargsources.append(arg_llsig_to_oopsig[i]) RGenOp = hrtyper.RGenOp self.args_gv = [None] * nb_args @@ -70,7 +70,7 @@ else: typename, method = operation_name.split('.') method = 'oop_%s_%s' % (typename, method) - SELFTYPE = FUNCTYPE.ARGS[self.argpositions[0]].TO + SELFTYPE = FUNCTYPE.ARGS[self.argtuple[0].n].TO self.is_method = True vmodule = __import__('pypy.jit.timeshifter.v%s' % (typename,), @@ -87,15 +87,20 @@ if self.couldfold: ARGS = FUNCTYPE.ARGS - argpos = unrolling_iterable(enumerate(self.argpositions)) + residualargsources = self.residualargsources + unrolling_ARGS = unrolling_iterable(ARGS) def do_call(jitstate, argboxes): - args = (None,)*nb_args - for i, pos in argpos: - if pos >= 0: - T = ARGS[pos] - v = rvalue.ll_getvalue(argboxes[i], T) - args = args[:pos] +(v,) + args[pos+1:] + args = () + j = 0 + for ARG in unrolling_ARGS: + if ARG == lltype.Void: + v = None + else: + argsrc = residualargsources[j] + j = j + 1 + v = rvalue.ll_getvalue(argboxes[argsrc], ARG) + args += (v,) result = fnptr(*args) if FUNCTYPE.RESULT == lltype.Void: return None @@ -110,15 +115,12 @@ def residual_call(self, jitstate, argboxes, deepfrozen=False): builder = jitstate.curbuilder - args_gv = self.args_gv[:] - argpositions = self.argpositions + args_gv = [] fold = deepfrozen - for i in range(len(argpositions)): - pos = argpositions[i] - if pos >= 0: - gv_arg = argboxes[i].getgenvar(builder) - args_gv[pos] = gv_arg - fold &= gv_arg.is_const + for argsrc in self.residualargsources: + gv_arg = argboxes[argsrc].getgenvar(builder) + args_gv.append(gv_arg) + fold &= gv_arg.is_const if fold: try: return self.do_call(jitstate, argboxes) Modified: pypy/branch/jit-real-world/pypy/jit/timeshifter/vdict.py ============================================================================== --- pypy/branch/jit-real-world/pypy/jit/timeshifter/vdict.py (original) +++ pypy/branch/jit-real-world/pypy/jit/timeshifter/vdict.py Mon Dec 4 00:11:35 2006 @@ -203,7 +203,7 @@ typedesc = self.typedesc items = self.getitems_and_makeempty(builder.rgenop) - args_gv = [None] + args_gv = [] gv_dict = builder.genop_call(typedesc.tok_ll_newdict, typedesc.gv_ll_newdict, args_gv) Modified: pypy/branch/jit-real-world/pypy/jit/timeshifter/vlist.py ============================================================================== --- pypy/branch/jit-real-world/pypy/jit/timeshifter/vlist.py (original) +++ pypy/branch/jit-real-world/pypy/jit/timeshifter/vlist.py Mon Dec 4 00:11:35 2006 @@ -112,7 +112,7 @@ boxes = self.item_boxes self.item_boxes = None - args_gv = [None, builder.rgenop.genconst(len(boxes))] + args_gv = [builder.rgenop.genconst(len(boxes))] gv_list = builder.genop_call(typedesc.tok_ll_newlist, typedesc.gv_ll_newlist, args_gv) From arigo at codespeak.net Mon Dec 4 01:32:49 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 4 Dec 2006 01:32:49 +0100 (CET) Subject: [pypy-svn] r35238 - in pypy/branch/jit-real-world/pypy/jit: codegen/i386 goal hintannotator timeshifter timeshifter/test Message-ID: <20061204003249.5A20E10050@code0.codespeak.net> Author: arigo Date: Mon Dec 4 01:32:45 2006 New Revision: 35238 Modified: pypy/branch/jit-real-world/pypy/jit/codegen/i386/rgenop.py pypy/branch/jit-real-world/pypy/jit/goal/jitstep.py pypy/branch/jit-real-world/pypy/jit/hintannotator/bookkeeper.py pypy/branch/jit-real-world/pypy/jit/hintannotator/model.py pypy/branch/jit-real-world/pypy/jit/timeshifter/hrtyper.py pypy/branch/jit-real-world/pypy/jit/timeshifter/rcontainer.py pypy/branch/jit-real-world/pypy/jit/timeshifter/test/test_timeshift.py Log: (pedronis, arigo) More and more fun with Voids. Modified: pypy/branch/jit-real-world/pypy/jit/codegen/i386/rgenop.py ============================================================================== --- pypy/branch/jit-real-world/pypy/jit/codegen/i386/rgenop.py (original) +++ pypy/branch/jit-real-world/pypy/jit/codegen/i386/rgenop.py Mon Dec 4 01:32:45 2006 @@ -956,12 +956,18 @@ @staticmethod @specialize.memo() def kindToken(T): + if T is lltype.Float: + raise NotImplementedError("floats in the i386 back-end") return None # for now @staticmethod @specialize.memo() def sigToken(FUNCTYPE): - return len(FUNCTYPE.ARGS) # for now + numargs = 0 + for ARG in FUNCTYPE.ARGS: + if ARG is not lltype.Void: + numargs += 1 + return numargs # for now @staticmethod def erasedType(T): Modified: pypy/branch/jit-real-world/pypy/jit/goal/jitstep.py ============================================================================== --- pypy/branch/jit-real-world/pypy/jit/goal/jitstep.py (original) +++ pypy/branch/jit-real-world/pypy/jit/goal/jitstep.py Mon Dec 4 01:32:45 2006 @@ -63,4 +63,4 @@ t.graphs.append(graph) # XXX temp - drv.compile() + drv.source() Modified: pypy/branch/jit-real-world/pypy/jit/hintannotator/bookkeeper.py ============================================================================== --- pypy/branch/jit-real-world/pypy/jit/hintannotator/bookkeeper.py (original) +++ pypy/branch/jit-real-world/pypy/jit/hintannotator/bookkeeper.py Mon Dec 4 01:32:45 2006 @@ -145,14 +145,6 @@ def immutablevalue(self, value): return self.immutableconstant(Constant(value, lltype.typeOf(value))) - def valueoftype(self, TYPE): - # the union of all annotations of the given TYPE - that's a - # SomeLLAbstractVariable, unless TYPE is Void - if TYPE is lltype.Void: - return hintmodel.s_void - else: - return hintmodel.SomeLLAbstractVariable(TYPE) - def current_op_concretetype(self): _, block, i = self.position_key op = block.operations[i] Modified: pypy/branch/jit-real-world/pypy/jit/hintannotator/model.py ============================================================================== --- pypy/branch/jit-real-world/pypy/jit/hintannotator/model.py (original) +++ pypy/branch/jit-real-world/pypy/jit/hintannotator/model.py Mon Dec 4 01:32:45 2006 @@ -204,6 +204,14 @@ SomeLLAbstractValue.__init__(self, T, deepfrozen) assert T is not lltype.Void # use bookkeeper.valueoftype() +def variableoftype(TYPE, deepfrozen=False): + # the union of all annotations of the given TYPE - that's a + # SomeLLAbstractVariable, unless TYPE is Void + if TYPE is lltype.Void: + return s_void + else: + return SomeLLAbstractVariable(TYPE, deepfrozen=deepfrozen) + class SomeLLAbstractContainer(SomeLLAbstractValue): deepfrozen = False # XXX for now @@ -299,7 +307,7 @@ def getfield(hs_v1, hs_fieldname): S = hs_v1.concretetype.TO FIELD_TYPE = getattr(S, hs_fieldname.const) - return SomeLLAbstractVariable(FIELD_TYPE, hs_v1.deepfrozen) + return variableoftype(FIELD_TYPE, hs_v1.deepfrozen) def setfield(hs_v1, hs_fieldname, hs_value): pass @@ -309,17 +317,6 @@ FIELD_TYPE = getattr(S, hs_fieldname.const) return SomeLLAbstractVariable(lltype.Ptr(FIELD_TYPE), hs_v1.deepfrozen) -## def getarrayitem(hs_v1, hs_index): -## ARRAY = hs_v1.concretetype.TO -## return SomeLLAbstractVariable(ARRAY.OF) - -## def setarrayitem(hs_v1, hs_index, hs_value): -## pass - -## def getarraysubstruct(hs_v1, hs_index): -## ARRAY = hs_v1.concretetype.TO -## return SomeLLAbstractVariable(lltype.Ptr(ARRAY.OF)) - def indirect_call(hs_v1, *args_hs): hs_graph_list = args_hs[-1] args_hs = args_hs[:-1] @@ -329,7 +326,7 @@ bookkeeper = getbookkeeper() if not bookkeeper.annotator.policy.look_inside_graphs(graph_list): # cannot follow - return bookkeeper.valueoftype(hs_v1.concretetype.TO.RESULT) + return variableoftype(hs_v1.concretetype.TO.RESULT) fixed = bookkeeper.myorigin().read_fixed() hs_res = bookkeeper.graph_family_call(graph_list, fixed, args_hs) @@ -379,19 +376,19 @@ pass # don't try to annotate suggested_primitive graphs if getattr(getattr(fnobj, '_callable', None), 'suggested_primitive', False): - return SomeLLAbstractVariable(lltype.typeOf(fnobj).RESULT) + return variableoftype(lltype.typeOf(fnobj).RESULT) # normal call if not hasattr(fnobj, 'graph'): raise NotImplementedError("XXX call to externals or primitives") if not bookkeeper.annotator.policy.look_inside_graph(fnobj.graph): - return bookkeeper.valueoftype(lltype.typeOf(fnobj).RESULT) + return variableoftype(lltype.typeOf(fnobj).RESULT) # recursive call from the entry point to itself: ignore them and # just hope the annotations are correct if (bookkeeper.getdesc(fnobj.graph)._cache.get(None, None) is bookkeeper.annotator.translator.graphs[0]): - return SomeLLAbstractVariable(lltype.typeOf(fnobj).RESULT) + return variableoftype(lltype.typeOf(fnobj).RESULT) fixed = bookkeeper.myorigin().read_fixed() hs_res = bookkeeper.graph_call(fnobj.graph, fixed, args_hs) @@ -421,7 +418,7 @@ myorigin=origin, deepfrozen=hs_c1.deepfrozen) else: - return SomeLLAbstractVariable(FIELD_TYPE) + return variableoftype(FIELD_TYPE) def getsubstruct(hs_c1, hs_fieldname): S = hs_c1.concretetype.TO @@ -468,8 +465,7 @@ class __extend__(pairtype(SomeLLAbstractValue, SomeLLAbstractValue)): def getarrayitem((hs_v1, hs_v2)): - return SomeLLAbstractVariable(hs_v1.concretetype.TO.OF, - hs_v1.deepfrozen) + return variableoftype(hs_v1.concretetype.TO.OF, hs_v1.deepfrozen) def setarrayitem((hs_v1, hs_v2), hs_v3): pass @@ -500,7 +496,7 @@ if (getattr(hs_v1, 'eager_concrete', False) or getattr(hs_v2, 'eager_concrete', False)): pair(hs_v1, hs_v2).invalid_union() - return SomeLLAbstractVariable(hs_v1.concretetype, hs_v1.deepfrozen) + return variableoftype(hs_v1.concretetype, hs_v1.deepfrozen) class __extend__(pairtype(SomeLLAbstractConstant, SomeLLAbstractConstant)): @@ -530,7 +526,7 @@ myorigin=origin, deepfrozen=hs_c1.deepfrozen) else: - return SomeLLAbstractVariable(READ_TYPE) + return variableoftype(READ_TYPE) def getarraysubstruct((hs_c1, hs_index)): A = hs_c1.concretetype.TO @@ -588,10 +584,7 @@ if bookkeeper.annotator.policy.novirtualcontainer: # "blue variables" disabled, we just return a red var all the time. RESULT = bookkeeper.current_op_concretetype() - if RESULT is lltype.Void: - return None - else: - return SomeLLAbstractVariable(RESULT) + return variableoftype(RESULT) # parse the oopspec and fill in the arguments operation_name, args = ll_func.oopspec.split('(', 1) Modified: pypy/branch/jit-real-world/pypy/jit/timeshifter/hrtyper.py ============================================================================== --- pypy/branch/jit-real-world/pypy/jit/timeshifter/hrtyper.py (original) +++ pypy/branch/jit-real-world/pypy/jit/timeshifter/hrtyper.py Mon Dec 4 01:32:45 2006 @@ -677,6 +677,8 @@ c_deepfrozen = inputconst(lltype.Bool, hop.args_s[0].deepfrozen) structdesc = rcontainer.StructTypeDesc(self.RGenOp, PTRTYPE.TO) fielddesc = structdesc.getfielddesc(c_fieldname.value) + if fielddesc is None: # Void field + return c_fielddesc = inputconst(lltype.Void, fielddesc) s_fielddesc = ts.rtyper.annotator.bookkeeper.immutablevalue(fielddesc) v_jitstate = hop.llops.getjitstate() @@ -687,6 +689,8 @@ def translate_op_getarrayitem(self, hop): PTRTYPE = originalconcretetype(hop.args_s[0]) + if PTRTYPE.TO.OF is lltype.Void: + return ts = self v_argbox, v_index = hop.inputargs(self.getredrepr(PTRTYPE), self.getredrepr(lltype.Signed)) @@ -751,6 +755,7 @@ v_destbox = hop.llops.as_ptrredbox(v_destbox) structdesc = rcontainer.StructTypeDesc(self.RGenOp, PTRTYPE.TO) fielddesc = structdesc.getfielddesc(c_fieldname.value) + assert fielddesc is not None # skipped above c_fielddesc = inputconst(lltype.Void, fielddesc) s_fielddesc = ts.rtyper.annotator.bookkeeper.immutablevalue(fielddesc) v_jitstate = hop.llops.getjitstate() Modified: pypy/branch/jit-real-world/pypy/jit/timeshifter/rcontainer.py ============================================================================== --- pypy/branch/jit-real-world/pypy/jit/timeshifter/rcontainer.py (original) +++ pypy/branch/jit-real-world/pypy/jit/timeshifter/rcontainer.py Mon Dec 4 01:32:45 2006 @@ -73,7 +73,7 @@ desc = None else: desc = StructFieldDesc(RGenOp, self.PTRTYPE, name, index) - fielddescs.append(desc) + fielddescs.append(desc) fielddesc_by_name[name] = desc self.fielddescs = fielddescs self.fielddesc_by_name = fielddesc_by_name @@ -120,6 +120,7 @@ # XXX basic field descs for now class FieldDesc(object): __metaclass__ = cachedtype + allow_void = False def __init__(self, RGenOp, PTRTYPE, RESTYPE): self.PTRTYPE = PTRTYPE @@ -128,7 +129,10 @@ self.RESTYPE = RESTYPE self.ptrkind = RGenOp.kindToken(PTRTYPE) self.kind = RGenOp.kindToken(RESTYPE) - self.redboxcls = rvalue.ll_redboxcls(RESTYPE) + if RESTYPE is lltype.Void and self.allow_void: + pass # no redboxcls at all + else: + self.redboxcls = rvalue.ll_redboxcls(RESTYPE) self.immutable = PTRTYPE.TO._hints.get('immutable', False) def _freeze_(self): @@ -165,6 +169,8 @@ self.defaultbox = self.redboxcls(self.kind, self.gv_default) class ArrayFieldDesc(FieldDesc): + allow_void = True + def __init__(self, RGenOp, TYPE): assert isinstance(TYPE, lltype.Array) FieldDesc.__init__(self, RGenOp, lltype.Ptr(TYPE), TYPE.OF) Modified: pypy/branch/jit-real-world/pypy/jit/timeshifter/test/test_timeshift.py ============================================================================== --- pypy/branch/jit-real-world/pypy/jit/timeshifter/test/test_timeshift.py (original) +++ pypy/branch/jit-real-world/pypy/jit/timeshifter/test/test_timeshift.py Mon Dec 4 01:32:45 2006 @@ -681,6 +681,16 @@ res = self.timeshift(ll_function, [0], []) assert res == 4 * 4 + def test_degenerate_with_voids(self): + S = lltype.GcStruct('S', ('y', lltype.Void), + ('x', lltype.Signed)) + def ll_function(): + s = lltype.malloc(S) + s.x = 123 + return s + res = self.timeshift(ll_function, [], [], policy=P_NOVIRTUAL) + assert res.x == 123 + def test_plus_minus_all_inlined(self): def ll_plus_minus(s, x, y): acc = x @@ -793,6 +803,20 @@ assert res == -42 self.check_insns(malloc_varsize=1) + def test_array_of_voids(self): + A = lltype.GcArray(lltype.Void) + def ll_function(n): + a = lltype.malloc(A, 3) + a[1] = None + b = a[n] + res = a, b + keepalive_until_here(b) # to keep getarrayitem around + return res + + res = self.timeshift(ll_function, [2], [], policy=P_NOVIRTUAL) + assert lltype.typeOf(res.item0) == lltype.Ptr(A) + assert res.item1 is None + def test_red_propagate(self): S = lltype.GcStruct('S', ('n', lltype.Signed)) def ll_function(n, k): From ericvrp at codespeak.net Mon Dec 4 10:53:26 2006 From: ericvrp at codespeak.net (ericvrp at codespeak.net) Date: Mon, 4 Dec 2006 10:53:26 +0100 (CET) Subject: [pypy-svn] r35243 - in pypy/dist/pypy/jit/codegen/llvm: . test Message-ID: <20061204095326.40D5B1006E@code0.codespeak.net> Author: ericvrp Date: Mon Dec 4 10:53:20 2006 New Revision: 35243 Added: pypy/dist/pypy/jit/codegen/llvm/conftest.py (contents, props changed) pypy/dist/pypy/jit/codegen/llvm/rgenop.py (contents, props changed) pypy/dist/pypy/jit/codegen/llvm/test/__init__.py (contents, props changed) pypy/dist/pypy/jit/codegen/llvm/test/test_genc_exception.py (contents, props changed) pypy/dist/pypy/jit/codegen/llvm/test/test_genc_tl.py (contents, props changed) pypy/dist/pypy/jit/codegen/llvm/test/test_genc_ts.py (contents, props changed) pypy/dist/pypy/jit/codegen/llvm/test/test_rgenop.py (contents, props changed) Log: codegen/llvm borrows tests from codegen/i386. All these tests are skipped though! Added: pypy/dist/pypy/jit/codegen/llvm/conftest.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/jit/codegen/llvm/conftest.py Mon Dec 4 10:53:20 2006 @@ -0,0 +1,17 @@ +import py +from pypy.jit.codegen import detect_cpu + +#XXX Should check here if llvm supports a JIT for this platform (perhaps using lli?) + +#class Directory(py.test.collect.Directory): +# +# def run(self): +# try: +# processor = detect_cpu.autodetect() +# except detect_cpu.ProcessorAutodetectError, e: +# py.test.skip(str(e)) +# else: +# if processor != 'i386': +# py.test.skip('detected a %r CPU' % (processor,)) +# +# return super(Directory, self).run() Added: pypy/dist/pypy/jit/codegen/llvm/rgenop.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/jit/codegen/llvm/rgenop.py Mon Dec 4 10:53:20 2006 @@ -0,0 +1,8 @@ +from pypy.jit.codegen.model import AbstractRGenOp, GenLabel, GenBuilder +from pypy.jit.codegen.model import GenVar, GenConst, CodeGenSwitch + +class RLLVMGenOp(AbstractRGenOp): + pass + +global_rgenop = RLLVMGenOp() +#XXX RLLVMGenOp.constPrebuiltGlobal = global_rgenop.genconst Added: pypy/dist/pypy/jit/codegen/llvm/test/__init__.py ============================================================================== Added: pypy/dist/pypy/jit/codegen/llvm/test/test_genc_exception.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/jit/codegen/llvm/test/test_genc_exception.py Mon Dec 4 10:53:20 2006 @@ -0,0 +1,13 @@ +import py +from pypy.jit.timeshifter.test import test_exception +from pypy.jit.codegen.llvm.test.test_genc_ts import LLVMTimeshiftingTestMixin + +py.test.skip("WIP") + +class TestException(LLVMTimeshiftingTestMixin, + test_exception.TestException): + + # for the individual tests see + # ====> ../../../timeshifter/test/test_exception.py + + pass Added: pypy/dist/pypy/jit/codegen/llvm/test/test_genc_tl.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/jit/codegen/llvm/test/test_genc_tl.py Mon Dec 4 10:53:20 2006 @@ -0,0 +1,14 @@ +import py +from pypy.jit.timeshifter.test import test_tl +from pypy.jit.codegen.llvm.test.test_genc_ts import LLVMTimeshiftingTestMixin + + +py.test.skip("WIP") + +class TestTLR(LLVMTimeshiftingTestMixin, + test_tl.TestTL): + + # for the individual tests see + # ====> ../../../timeshifter/test/test_tl.py + + pass Added: pypy/dist/pypy/jit/codegen/llvm/test/test_genc_ts.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/jit/codegen/llvm/test/test_genc_ts.py Mon Dec 4 10:53:20 2006 @@ -0,0 +1,19 @@ +import py +from pypy.jit.codegen.i386.test.test_genc_ts import I386TimeshiftingTestMixin +from pypy.jit.timeshifter.test import test_timeshift +from pypy.jit.codegen.llvm.rgenop import RLLVMGenOp + + +py.test.skip("WIP") + +class LLVMTimeshiftingTestMixin(I386TimeshiftingTestMixin): + RGenOp = RLLVMGenOp + +class TestTimeshiftLLVM(LLVMTimeshiftingTestMixin, + test_timeshift.TestTimeshift): + + # for the individual tests see + # ====> ../../../timeshifter/test/test_timeshift.py + + pass + Added: pypy/dist/pypy/jit/codegen/llvm/test/test_rgenop.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/jit/codegen/llvm/test/test_rgenop.py Mon Dec 4 10:53:20 2006 @@ -0,0 +1,9 @@ +import py +from pypy.jit.codegen.llvm.rgenop import RLLVMGenOp +from pypy.jit.codegen.test.rgenop_tests import AbstractRGenOpTests + + +py.test.skip("WIP") + +class TestRLLVMGenop(AbstractRGenOpTests): + RGenOp = RLLVMGenOp From cfbolz at codespeak.net Mon Dec 4 11:38:19 2006 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Mon, 4 Dec 2006 11:38:19 +0100 (CET) Subject: [pypy-svn] r35244 - pypy/extradoc/talk/warsaw2006 Message-ID: <20061204103819.0129D1006F@code0.codespeak.net> Author: cfbolz Date: Mon Dec 4 11:38:14 2006 New Revision: 35244 Added: pypy/extradoc/talk/warsaw2006/MochiKit.js Log: add mochikit, to hopefully make the web generation not choke Added: pypy/extradoc/talk/warsaw2006/MochiKit.js ============================================================================== --- (empty file) +++ pypy/extradoc/talk/warsaw2006/MochiKit.js Mon Dec 4 11:38:14 2006 @@ -0,0 +1,6854 @@ +/*** + + MochiKit.MochiKit 1.4 : PACKED VERSION + + THIS FILE IS AUTOMATICALLY GENERATED. If creating patches, please + diff against the source tree, not this file. + + See for documentation, downloads, license, etc. + + (c) 2005 Bob Ippolito. All rights Reserved. + +***/ + +if(typeof (dojo)!="undefined"){ +dojo.provide("MochiKit.Base"); +} +if(typeof (MochiKit)=="undefined"){ +MochiKit={}; +} +if(typeof (MochiKit.Base)=="undefined"){ +MochiKit.Base={}; +} +MochiKit.Base.VERSION="1.4"; +MochiKit.Base.NAME="MochiKit.Base"; +MochiKit.Base.update=function(_1,_2){ +if(_1===null){ +_1={}; +} +for(var i=1;i=0;i--){ +_15.unshift(o[i]); +} +}else{ +res.push(o); +} +} +return res; +},extend:function(_16,obj,_17){ +if(!_17){ +_17=0; +} +if(obj){ +var l=obj.length; +if(typeof (l)!="number"){ +if(typeof (MochiKit.Iter)!="undefined"){ +obj=MochiKit.Iter.list(obj); +l=obj.length; +}else{ +throw new TypeError("Argument not an array-like and MochiKit.Iter not present"); +} +} +if(!_16){ +_16=[]; +} +for(var i=_17;i>b; +},zrshift:function(a,b){ +return a>>>b; +},eq:function(a,b){ +return a==b; +},ne:function(a,b){ +return a!=b; +},gt:function(a,b){ +return a>b; +},ge:function(a,b){ +return a>=b; +},lt:function(a,b){ +return al){ +_42=l; +} +} +_41=[]; +for(i=0;i<_42;i++){ +var _43=[]; +for(var j=1;j=0;i--){ +_57=[_56[i].apply(this,_57)]; +} +return _57[0]; +}; +},bind:function(_58,_59){ +if(typeof (_58)=="string"){ +_58=_59[_58]; +} +var _60=_58.im_func; +var _61=_58.im_preargs; +var _62=_58.im_self; +var m=MochiKit.Base; +if(typeof (_58)=="function"&&typeof (_58.apply)=="undefined"){ +_58=m._wrapDumbFunction(_58); +} +if(typeof (_60)!="function"){ +_60=_58; +} +if(typeof (_59)!="undefined"){ +_62=_59; +} +if(typeof (_61)=="undefined"){ +_61=[]; +}else{ +_61=_61.slice(); +} +m.extend(_61,arguments,2); +var _63=function(){ +var _64=arguments; +var me=arguments.callee; +if(me.im_preargs.length>0){ +_64=m.concat(me.im_preargs,_64); +} +var _59=me.im_self; +if(!_59){ +_59=this; +} +return me.im_func.apply(_59,_64); +}; +_63.im_self=_62; +_63.im_func=_60; +_63.im_preargs=_61; +return _63; +},bindMethods:function(_65){ +var _66=MochiKit.Base.bind; +for(var k in _65){ +var _67=_65[k]; +if(typeof (_67)=="function"){ +_65[k]=_66(_67,_65); +} +} +},registerComparator:function(_68,_69,_70,_71){ +MochiKit.Base.comparatorRegistry.register(_68,_69,_70,_71); +},_primitives:{"boolean":true,"string":true,"number":true},compare:function(a,b){ +if(a==b){ +return 0; +} +var _72=(typeof (a)=="undefined"||a===null); +var _73=(typeof (b)=="undefined"||b===null); +if(_72&&_73){ +return 0; +}else{ +if(_72){ +return -1; +}else{ +if(_73){ +return 1; +} +} +} +var m=MochiKit.Base; +var _74=m._primitives; +if(!(typeof (a) in _74&&typeof (b) in _74)){ +try{ +return m.comparatorRegistry.match(a,b); +} +catch(e){ +if(e!=m.NotFound){ +throw e; +} +} +} +if(ab){ +return 1; +} +} +var _75=m.repr; +throw new TypeError(_75(a)+" and "+_75(b)+" can not be compared"); +},compareDateLike:function(a,b){ +return MochiKit.Base.compare(a.getTime(),b.getTime()); +},compareArrayLike:function(a,b){ +var _76=MochiKit.Base.compare; +var _77=a.length; +var _78=0; +if(_77>b.length){ +_78=1; +_77=b.length; +}else{ +if(_770))){ +var kv=MochiKit.DOM.formContents(_120); +_120=kv[0]; +_121=kv[1]; +}else{ +if(arguments.length==1){ +var o=_120; +_120=[]; +_121=[]; +for(var k in o){ +var v=o[k]; +if(typeof (v)!="function"){ +_120.push(k); +_121.push(v); +} +} +} +} +var rval=[]; +var len=Math.min(_120.length,_121.length); +var _124=MochiKit.Base.urlEncode; +for(var i=0;i=stop){ +throw self.StopIteration; +} +_153+=step; +return rval; +}}; +},imap:function(fun,p,q){ +var m=MochiKit.Base; +var self=MochiKit.Iter; +var _157=m.map(self.iter,m.extend(null,arguments,1)); +var map=m.map; +var next=self.next; +return {repr:function(){ +return "imap(...)"; +},toString:m.forwardCall("repr"),next:function(){ +return fun.apply(this,map(next,_157)); +}}; +},applymap:function(fun,seq,self){ +seq=MochiKit.Iter.iter(seq); +var m=MochiKit.Base; +return {repr:function(){ +return "applymap(...)"; +},toString:m.forwardCall("repr"),next:function(){ +return fun.apply(self,seq.next()); +}}; +},chain:function(p,q){ +var self=MochiKit.Iter; +var m=MochiKit.Base; +if(arguments.length==1){ +return self.iter(arguments[0]); +} +var _159=m.map(self.iter,arguments); +return {repr:function(){ +return "chain(...)"; +},toString:m.forwardCall("repr"),next:function(){ +while(_159.length>1){ +try{ +return _159[0].next(); +} +catch(e){ +if(e!=self.StopIteration){ +throw e; +} +_159.shift(); +} +} +if(_159.length==1){ +var arg=_159.shift(); +this.next=m.bind("next",arg); +return this.next(); +} +throw self.StopIteration; +}}; +},takewhile:function(pred,seq){ +var self=MochiKit.Iter; +seq=self.iter(seq); +return {repr:function(){ +return "takewhile(...)"; +},toString:MochiKit.Base.forwardCall("repr"),next:function(){ +var rval=seq.next(); +if(!pred(rval)){ +this.next=function(){ +throw self.StopIteration; +}; +this.next(); +} +return rval; +}}; +},dropwhile:function(pred,seq){ +seq=MochiKit.Iter.iter(seq); +var m=MochiKit.Base; +var bind=m.bind; +return {"repr":function(){ +return "dropwhile(...)"; +},"toString":m.forwardCall("repr"),"next":function(){ +while(true){ +var rval=seq.next(); +if(!pred(rval)){ +break; +} +} +this.next=bind("next",seq); +return rval; +}}; +},_tee:function(_161,sync,_163){ +sync.pos[_161]=-1; +var m=MochiKit.Base; +var _164=m.listMin; +return {repr:function(){ +return "tee("+_161+", ...)"; +},toString:m.forwardCall("repr"),next:function(){ +var rval; +var i=sync.pos[_161]; +if(i==sync.max){ +rval=_163.next(); +sync.deque.push(rval); +sync.max+=1; +sync.pos[_161]+=1; +}else{ +rval=sync.deque[i-sync.min]; +sync.pos[_161]+=1; +if(i==sync.min&&_164(sync.pos)!=sync.min){ +sync.min+=1; +sync.deque.shift(); +} +} +return rval; +}}; +},tee:function(_165,n){ +var rval=[]; +var sync={"pos":[],"deque":[],"max":-1,"min":-1}; +if(arguments.length==1||typeof (n)=="undefined"||n===null){ +n=2; +} +var self=MochiKit.Iter; +_165=self.iter(_165); +var _tee=self._tee; +for(var i=0;i0&&_171>=stop)||(step<0&&_171<=stop)){ +throw MochiKit.Iter.StopIteration; +} +var rval=_171; +_171+=step; +return rval; +},repr:function(){ +return "range("+[_171,stop,step].join(", ")+")"; +},toString:MochiKit.Base.forwardCall("repr")}; +},sum:function(_172,_173){ +if(typeof (_173)=="undefined"||_173===null){ +_173=0; +} +var x=_173; +var self=MochiKit.Iter; +_172=self.iter(_172); +try{ +while(true){ +x+=_172.next(); +} +} +catch(e){ +if(e!=self.StopIteration){ +throw e; +} +} +return x; +},exhaust:function(_174){ +var self=MochiKit.Iter; +_174=self.iter(_174); +try{ +while(true){ +_174.next(); +} +} +catch(e){ +if(e!=self.StopIteration){ +throw e; +} +} +},forEach:function(_175,func,self){ +var m=MochiKit.Base; +if(arguments.length>2){ +func=m.bind(func,self); +} +if(m.isArrayLike(_175)){ +try{ +for(var i=0;i<_175.length;i++){ +func(_175[i]); +} +} +catch(e){ +if(e!=MochiKit.Iter.StopIteration){ +throw e; +} +} +}else{ +self=MochiKit.Iter; +self.exhaust(self.imap(func,_175)); +} +},every:function(_176,func){ +var self=MochiKit.Iter; +try{ +self.ifilterfalse(func,_176).next(); +return false; +} +catch(e){ +if(e!=self.StopIteration){ +throw e; +} +return true; +} +},sorted:function(_177,cmp){ +var rval=MochiKit.Iter.list(_177); +if(arguments.length==1){ +cmp=MochiKit.Base.compare; +} +rval.sort(cmp); +return rval; +},reversed:function(_178){ +var rval=MochiKit.Iter.list(_178); +rval.reverse(); +return rval; +},some:function(_179,func){ +var self=MochiKit.Iter; +try{ +self.ifilter(func,_179).next(); +return true; +} +catch(e){ +if(e!=self.StopIteration){ +throw e; +} +return false; +} +},iextend:function(lst,_180){ +if(MochiKit.Base.isArrayLike(_180)){ +for(var i=0;i<_180.length;i++){ +lst.push(_180[i]); +} +}else{ +var self=MochiKit.Iter; +_180=self.iter(_180); +try{ +while(true){ +lst.push(_180.next()); +} +} +catch(e){ +if(e!=self.StopIteration){ +throw e; +} +} +} +return lst; +},groupby:function(_181,_182){ +var m=MochiKit.Base; +var self=MochiKit.Iter; +if(arguments.length<2){ +_182=m.operator.identity; +} +_181=self.iter(_181); +var pk=undefined; +var k=undefined; +var v; +function fetch(){ +v=_181.next(); +k=_182(v); +} +function eat(){ +var ret=v; +v=undefined; +return ret; +} +var _185=true; +return {repr:function(){ +return "groupby(...)"; +},next:function(){ +while(k==pk){ +fetch(); +if(_185){ +_185=false; +break; +} +} +pk=k; +return [k,{next:function(){ +if(v==undefined){ +fetch(); +} +if(k!=pk){ +throw self.StopIteration; +} +return eat(); +}}]; +}}; +},groupby_as_array:function(_186,_187){ +var m=MochiKit.Base; +var self=MochiKit.Iter; +if(arguments.length<2){ +_187=m.operator.identity; +} +_186=self.iter(_186); +var _188=[]; +var _189=true; +var _190; +while(true){ +try{ +var _191=_186.next(); +var key=_187(_191); +} +catch(e){ +if(e==self.StopIteration){ +break; +} +throw e; +} +if(_189||key!=_190){ +var _192=[]; +_188.push([key,_192]); +} +_192.push(_191); +_189=false; +_190=key; +} +return _188; +},arrayLikeIter:function(_193){ +var i=0; +return {repr:function(){ +return "arrayLikeIter(...)"; +},toString:MochiKit.Base.forwardCall("repr"),next:function(){ +if(i>=_193.length){ +throw MochiKit.Iter.StopIteration; +} +return _193[i++]; +}}; +},hasIterateNext:function(_194){ +return (_194&&typeof (_194.iterateNext)=="function"); +},iterateNextIter:function(_195){ +return {repr:function(){ +return "iterateNextIter(...)"; +},toString:MochiKit.Base.forwardCall("repr"),next:function(){ +var rval=_195.iterateNext(); +if(rval===null||rval===undefined){ +throw MochiKit.Iter.StopIteration; +} +return rval; +}}; +}}); +MochiKit.Iter.EXPORT_OK=["iteratorRegistry","arrayLikeIter","hasIterateNext","iterateNextIter",]; +MochiKit.Iter.EXPORT=["StopIteration","registerIteratorFactory","iter","count","cycle","repeat","next","izip","ifilter","ifilterfalse","islice","imap","applymap","chain","takewhile","dropwhile","tee","list","reduce","range","sum","exhaust","forEach","every","sorted","reversed","some","iextend","groupby","groupby_as_array"]; +MochiKit.Iter.__new__=function(){ +var m=MochiKit.Base; +if(typeof (StopIteration)!="undefined"){ +this.StopIteration=StopIteration; +}else{ +this.StopIteration=new m.NamedError("StopIteration"); +} +this.iteratorRegistry=new m.AdapterRegistry(); +this.registerIteratorFactory("arrayLike",m.isArrayLike,this.arrayLikeIter); +this.registerIteratorFactory("iterateNext",this.hasIterateNext,this.iterateNextIter); +this.EXPORT_TAGS={":common":this.EXPORT,":all":m.concat(this.EXPORT,this.EXPORT_OK)}; +m.nameFunctions(this); +}; +MochiKit.Iter.__new__(); +if(MochiKit.__export__){ +reduce=MochiKit.Iter.reduce; +} +MochiKit.Base._exportSymbols(this,MochiKit.Iter); +if(typeof (dojo)!="undefined"){ +dojo.provide("MochiKit.Logging"); +dojo.require("MochiKit.Base"); +} +if(typeof (JSAN)!="undefined"){ +JSAN.use("MochiKit.Base",[]); +} +try{ +if(typeof (MochiKit.Base)=="undefined"){ +throw ""; +} +} +catch(e){ +throw "MochiKit.Logging depends on MochiKit.Base!"; +} +if(typeof (MochiKit.Logging)=="undefined"){ +MochiKit.Logging={}; +} +MochiKit.Logging.NAME="MochiKit.Logging"; +MochiKit.Logging.VERSION="1.4"; +MochiKit.Logging.__repr__=function(){ +return "["+this.NAME+" "+this.VERSION+"]"; +}; +MochiKit.Logging.toString=function(){ +return this.__repr__(); +}; +MochiKit.Logging.EXPORT=["LogLevel","LogMessage","Logger","alertListener","logger","log","logError","logDebug","logFatal","logWarning"]; +MochiKit.Logging.EXPORT_OK=["logLevelAtLeast","isLogMessage","compareLogMessage"]; +MochiKit.Logging.LogMessage=function(num,_197,info){ +this.num=num; +this.level=_197; +this.info=info; +this.timestamp=new Date(); +}; +MochiKit.Logging.LogMessage.prototype={repr:function(){ +var m=MochiKit.Base; +return "LogMessage("+m.map(m.repr,[this.num,this.level,this.info]).join(", ")+")"; +},toString:MochiKit.Base.forwardCall("repr")}; +MochiKit.Base.update(MochiKit.Logging,{logLevelAtLeast:function(_199){ +var self=MochiKit.Logging; +if(typeof (_199)=="string"){ +_199=self.LogLevel[_199]; +} +return function(msg){ +var _201=msg.level; +if(typeof (_201)=="string"){ +_201=self.LogLevel[_201]; +} +return _201>=_199; +}; +},isLogMessage:function(){ +var _202=MochiKit.Logging.LogMessage; +for(var i=0;i=0&&this._messages.length>this.maxSize){ +this._messages.shift(); +} +},getMessages:function(_211){ +var _212=0; +if(!(typeof (_211)=="undefined"||_211===null)){ +_212=Math.max(0,this._messages.length-_211); +} +return this._messages.slice(_212); +},getMessageText:function(_213){ +if(typeof (_213)=="undefined"||_213===null){ +_213=30; +} +var _214=this.getMessages(_213); +if(_214.length){ +var lst=map(function(m){ +return "\n ["+m.num+"] "+m.level+": "+m.info.join(" "); +},_214); +lst.unshift("LAST "+_214.length+" MESSAGES:"); +return lst.join(""); +} +return ""; +},debuggingBookmarklet:function(_215){ +if(typeof (MochiKit.LoggingPane)=="undefined"){ +alert(this.getMessageText()); +}else{ +MochiKit.LoggingPane.createLoggingPane(_215||false); +} +}}; +MochiKit.Logging.__new__=function(){ +this.LogLevel={ERROR:40,FATAL:50,WARNING:30,INFO:20,DEBUG:10}; +var m=MochiKit.Base; +m.registerComparator("LogMessage",this.isLogMessage,this.compareLogMessage); +var _216=m.partial; +var _217=this.Logger; +var _218=_217.prototype.baseLog; +m.update(this.Logger.prototype,{debug:_216(_218,"DEBUG"),log:_216(_218,"INFO"),error:_216(_218,"ERROR"),fatal:_216(_218,"FATAL"),warning:_216(_218,"WARNING")}); +var self=this; +var _219=function(name){ +return function(){ +self.logger[name].apply(self.logger,arguments); +}; +}; +this.log=_219("log"); +this.logError=_219("error"); +this.logDebug=_219("debug"); +this.logFatal=_219("fatal"); +this.logWarning=_219("warning"); +this.logger=new _217(); +this.logger.useNativeConsole=true; +this.EXPORT_TAGS={":common":this.EXPORT,":all":m.concat(this.EXPORT,this.EXPORT_OK)}; +m.nameFunctions(this); +}; +if(typeof (printfire)=="undefined"&&typeof (document)!="undefined"&&document.createEvent&&typeof (dispatchEvent)!="undefined"){ +printfire=function(){ +printfire.args=arguments; +var ev=document.createEvent("Events"); +ev.initEvent("printfire",false,true); +dispatchEvent(ev); +}; +} +MochiKit.Logging.__new__(); +MochiKit.Base._exportSymbols(this,MochiKit.Logging); +if(typeof (dojo)!="undefined"){ +dojo.provide("MochiKit.DateTime"); +} +if(typeof (MochiKit)=="undefined"){ +MochiKit={}; +} +if(typeof (MochiKit.DateTime)=="undefined"){ +MochiKit.DateTime={}; +} +MochiKit.DateTime.NAME="MochiKit.DateTime"; +MochiKit.DateTime.VERSION="1.4"; +MochiKit.DateTime.__repr__=function(){ +return "["+this.NAME+" "+this.VERSION+"]"; +}; +MochiKit.DateTime.toString=function(){ +return this.__repr__(); +}; +MochiKit.DateTime.isoDate=function(str){ +str=str+""; +if(typeof (str)!="string"||str.length===0){ +return null; +} +var iso=str.split("-"); +if(iso.length===0){ +return null; +} +return new Date(iso[0],iso[1]-1,iso[2]); +}; +MochiKit.DateTime._isoRegexp=/(\d{4,})(?:-(\d{1,2})(?:-(\d{1,2})(?:[T ](\d{1,2}):(\d{1,2})(?::(\d{1,2})(?:\.(\d+))?)?(?:(Z)|([+-])(\d{1,2})(?::(\d{1,2}))?)?)?)?)?/; +MochiKit.DateTime.isoTimestamp=function(str){ +str=str+""; +if(typeof (str)!="string"||str.length===0){ +return null; +} +var res=str.match(MochiKit.DateTime._isoRegexp); +if(typeof (res)=="undefined"||res===null){ +return null; +} +var year,month,day,hour,min,sec,msec; +year=parseInt(res[1],10); +if(typeof (res[2])=="undefined"||res[2]===""){ +return new Date(year); +} +month=parseInt(res[2],10)-1; +day=parseInt(res[3],10); +if(typeof (res[4])=="undefined"||res[4]===""){ +return new Date(year,month,day); +} +hour=parseInt(res[4],10); +min=parseInt(res[5],10); +sec=(typeof (res[6])!="undefined"&&res[6]!=="")?parseInt(res[6],10):0; +if(typeof (res[7])!="undefined"&&res[7]!==""){ +msec=Math.round(1000*parseFloat("0."+res[7])); +}else{ +msec=0; +} +if((typeof (res[8])=="undefined"||res[8]==="")&&(typeof (res[9])=="undefined"||res[9]==="")){ +return new Date(year,month,day,hour,min,sec,msec); +} +var ofs; +if(typeof (res[9])!="undefined"&&res[9]!==""){ +ofs=parseInt(res[10],10)*3600000; +if(typeof (res[11])!="undefined"&&res[11]!==""){ +ofs+=parseInt(res[11],10)*60000; +} +if(res[9]=="-"){ +ofs=-ofs; +} +}else{ +ofs=0; +} +return new Date(Date.UTC(year,month,day,hour,min,sec,msec)-ofs); +}; +MochiKit.DateTime.toISOTime=function(date,_226){ +if(typeof (date)=="undefined"||date===null){ +return null; +} +var hh=date.getHours(); +var mm=date.getMinutes(); +var ss=date.getSeconds(); +var lst=[((_226&&(hh<10))?"0"+hh:hh),((mm<10)?"0"+mm:mm),((ss<10)?"0"+ss:ss)]; +return lst.join(":"); +}; +MochiKit.DateTime.toISOTimestamp=function(date,_230){ +if(typeof (date)=="undefined"||date===null){ +return null; +} +var sep=_230?"T":" "; +var foot=_230?"Z":""; +if(_230){ +date=new Date(date.getTime()+(date.getTimezoneOffset()*60000)); +} +return MochiKit.DateTime.toISODate(date)+sep+MochiKit.DateTime.toISOTime(date,_230)+foot; +}; +MochiKit.DateTime.toISODate=function(date){ +if(typeof (date)=="undefined"||date===null){ +return null; +} +var _233=MochiKit.DateTime._padTwo; +return [date.getFullYear(),_233(date.getMonth()+1),_233(date.getDate())].join("-"); +}; +MochiKit.DateTime.americanDate=function(d){ +d=d+""; +if(typeof (d)!="string"||d.length===0){ +return null; +} +var a=d.split("/"); +return new Date(a[2],a[0]-1,a[1]); +}; +MochiKit.DateTime._padTwo=function(n){ +return (n>9)?n:"0"+n; +}; +MochiKit.DateTime.toPaddedAmericanDate=function(d){ +if(typeof (d)=="undefined"||d===null){ +return null; +} +var _235=MochiKit.DateTime._padTwo; +return [_235(d.getMonth()+1),_235(d.getDate()),d.getFullYear()].join("/"); +}; +MochiKit.DateTime.toAmericanDate=function(d){ +if(typeof (d)=="undefined"||d===null){ +return null; +} +return [d.getMonth()+1,d.getDate(),d.getFullYear()].join("/"); +}; +MochiKit.DateTime.EXPORT=["isoDate","isoTimestamp","toISOTime","toISOTimestamp","toISODate","americanDate","toPaddedAmericanDate","toAmericanDate"]; +MochiKit.DateTime.EXPORT_OK=[]; +MochiKit.DateTime.EXPORT_TAGS={":common":MochiKit.DateTime.EXPORT,":all":MochiKit.DateTime.EXPORT}; +MochiKit.DateTime.__new__=function(){ +var base=this.NAME+"."; +for(var k in this){ +var o=this[k]; +if(typeof (o)=="function"&&typeof (o.NAME)=="undefined"){ +try{ +o.NAME=base+k; +} +catch(e){ +} +} +} +}; +MochiKit.DateTime.__new__(); +if(typeof (MochiKit.Base)!="undefined"){ +MochiKit.Base._exportSymbols(this,MochiKit.DateTime); +}else{ +(function(_236,_237){ +if((typeof (JSAN)=="undefined"&&typeof (dojo)=="undefined")||(MochiKit.__export__===false)){ +var all=_237.EXPORT_TAGS[":all"]; +for(var i=0;i_245){ +var i=_251.length-_245; +res=fmt.separator+_251.substring(i,_251.length)+res; +_251=_251.substring(0,i); +} +} +res=_251+res; +if(_243>0){ +while(frac.length<_246){ +frac=frac+"0"; +} +res=res+fmt.decimal+frac; +} +return _247+res+_248; +}; +}; +MochiKit.Format.numberFormatter=function(_253,_254,_255){ +if(typeof (_254)=="undefined"){ +_254=""; +} +var _256=_253.match(/((?:[0#]+,)?[0#]+)(?:\.([0#]+))?(%)?/); +if(!_256){ +throw TypeError("Invalid pattern"); +} +var _257=_253.substr(0,_256.index); +var _258=_253.substr(_256.index+_256[0].length); +if(_257.search(/-/)==-1){ +_257=_257+"-"; +} +var _259=_256[1]; +var frac=(typeof (_256[2])=="string"&&_256[2]!="")?_256[2]:""; +var _260=(typeof (_256[3])=="string"&&_256[3]!=""); +var tmp=_259.split(/,/); +var _262; +if(typeof (_255)=="undefined"){ +_255="default"; +} +if(tmp.length==1){ +_262=null; +}else{ +_262=tmp[1].length; +} +var _263=_259.length-_259.replace(/0/g,"").length; +var _264=frac.length-frac.replace(/0/g,"").length; +var _265=frac.length; +var rval=MochiKit.Format._numberFormatter(_254,_257,_258,_255,_260,_265,_263,_262,_264); +var m=MochiKit.Base; +if(m){ +var fn=arguments.callee; +var args=m.concat(arguments); +rval.repr=function(){ +return [self.NAME,"(",map(m.repr,args).join(", "),")"].join(""); +}; +} +return rval; +}; +MochiKit.Format.formatLocale=function(_267){ +if(typeof (_267)=="undefined"||_267===null){ +_267="default"; +} +if(typeof (_267)=="string"){ +var rval=MochiKit.Format.LOCALE[_267]; +if(typeof (rval)=="string"){ +rval=arguments.callee(rval); +MochiKit.Format.LOCALE[_267]=rval; +} +return rval; +}else{ +return _267; +} +}; +MochiKit.Format.twoDigitAverage=function(_268,_269){ +if(_269){ +var res=_268/_269; +if(!isNaN(res)){ +return MochiKit.Format.twoDigitFloat(_268/_269); +} +} +return "0"; +}; +MochiKit.Format.twoDigitFloat=function(_270){ +var sign=(_270<0?"-":""); +var s=Math.floor(Math.abs(_270)*100).toString(); +if(s=="0"){ +return s; +} +if(s.length<3){ +while(s.charAt(s.length-1)=="0"){ +s=s.substring(0,s.length-1); +} +return sign+"0."+s; +} +var head=sign+s.substring(0,s.length-2); +var tail=s.substring(s.length-2,s.length); +if(tail=="00"){ +return head; +}else{ +if(tail.charAt(1)=="0"){ +return head+"."+tail.charAt(0); +}else{ +return head+"."+tail; +} +} +}; +MochiKit.Format.lstrip=function(str,_275){ +str=str+""; +if(typeof (str)!="string"){ +return null; +} +if(!_275){ +return str.replace(/^\s+/,""); +}else{ +return str.replace(new RegExp("^["+_275+"]+"),""); +} +}; +MochiKit.Format.rstrip=function(str,_276){ +str=str+""; +if(typeof (str)!="string"){ +return null; +} +if(!_276){ +return str.replace(/\s+$/,""); +}else{ +return str.replace(new RegExp("["+_276+"]+$"),""); +} +}; +MochiKit.Format.strip=function(str,_277){ +var self=MochiKit.Format; +return self.rstrip(self.lstrip(str,_277),_277); +}; +MochiKit.Format.truncToFixed=function(_278,_279){ +_278=Math.floor(_278*Math.pow(10,_279)); +var res=(_278*Math.pow(10,-_279)).toFixed(_279); +if(res.charAt(0)=="."){ +res="0"+res; +} +return res; +}; +MochiKit.Format.roundToFixed=function(_280,_281){ +return MochiKit.Format.truncToFixed(_280+0.5*Math.pow(10,-_281),_281); +}; +MochiKit.Format.percentFormat=function(_282){ +return MochiKit.Format.twoDigitFloat(100*_282)+"%"; +}; +MochiKit.Format.EXPORT=["truncToFixed","roundToFixed","numberFormatter","formatLocale","twoDigitAverage","twoDigitFloat","percentFormat","lstrip","rstrip","strip"]; +MochiKit.Format.LOCALE={en_US:{separator:",",decimal:".",percent:"%"},de_DE:{separator:".",decimal:",",percent:"%"},fr_FR:{separator:" ",decimal:",",percent:"%"},"default":"en_US"}; +MochiKit.Format.EXPORT_OK=[]; +MochiKit.Format.EXPORT_TAGS={":all":MochiKit.Format.EXPORT,":common":MochiKit.Format.EXPORT}; +MochiKit.Format.__new__=function(){ +var base=this.NAME+"."; +var k,v,o; +for(k in this.LOCALE){ +o=this.LOCALE[k]; +if(typeof (o)=="object"){ +o.repr=function(){ +return this.NAME; +}; +o.NAME=base+"LOCALE."+k; +} +} +for(k in this){ +o=this[k]; +if(typeof (o)=="function"&&typeof (o.NAME)=="undefined"){ +try{ +o.NAME=base+k; +} +catch(e){ +} +} +} +}; +MochiKit.Format.__new__(); +if(typeof (MochiKit.Base)!="undefined"){ +MochiKit.Base._exportSymbols(this,MochiKit.Format); +}else{ +(function(_283,_284){ +if((typeof (JSAN)=="undefined"&&typeof (dojo)=="undefined")||(MochiKit.__export__===false)){ +var all=_284.EXPORT_TAGS[":all"]; +for(var i=0;i1){ +fn=MochiKit.Base.partial.apply(null,arguments); +} +return this.addCallbacks(fn,fn); +},addCallback:function(fn){ +if(arguments.length>1){ +fn=MochiKit.Base.partial.apply(null,arguments); +} +return this.addCallbacks(fn,null); +},addErrback:function(fn){ +if(arguments.length>1){ +fn=MochiKit.Base.partial.apply(null,arguments); +} +return this.addCallbacks(null,fn); +},addCallbacks:function(cb,eb){ +if(this.chained){ +throw new Error("Chained Deferreds can not be re-used"); +} +this.chain.push([cb,eb]); +if(this.fired>=0){ +this._fire(); +} +return this; +},_fire:function(){ +var _289=this.chain; +var _290=this.fired; +var res=this.results[_290]; +var self=this; +var cb=null; +while(_289.length>0&&this.paused===0){ +var pair=_289.shift(); +var f=pair[_290]; +if(f===null){ +continue; +} +try{ +res=f(res); +_290=((res instanceof Error)?1:0); +if(res instanceof MochiKit.Async.Deferred){ +cb=function(res){ +self._resback(res); +self.paused--; +if((self.paused===0)&&(self.fired>=0)){ +self._fire(); +} +}; +this.paused++; +} +} +catch(err){ +_290=1; +if(!(err instanceof Error)){ +err=new MochiKit.Async.GenericError(err); +} +res=err; +} +} +this.fired=_290; +this.results[_290]=res; +if(cb&&this.paused){ +res.addBoth(cb); +res.chained=true; +} +}}; +MochiKit.Base.update(MochiKit.Async,{evalJSONRequest:function(){ +return eval("("+arguments[0].responseText+")"); +},succeed:function(_292){ +var d=new MochiKit.Async.Deferred(); +d.callback.apply(d,arguments); +return d; +},fail:function(_293){ +var d=new MochiKit.Async.Deferred(); +d.errback.apply(d,arguments); +return d; +},getXMLHttpRequest:function(){ +var self=arguments.callee; +if(!self.XMLHttpRequest){ +var _294=[function(){ +return new XMLHttpRequest(); +},function(){ +return new ActiveXObject("Msxml2.XMLHTTP"); +},function(){ +return new ActiveXObject("Microsoft.XMLHTTP"); +},function(){ +return new ActiveXObject("Msxml2.XMLHTTP.4.0"); +},function(){ +throw new MochiKit.Async.BrowserComplianceError("Browser does not support XMLHttpRequest"); +}]; +for(var i=0;i<_294.length;i++){ +var func=_294[i]; +try{ +self.XMLHttpRequest=func; +return func(); +} +catch(e){ +} +} +} +return self.XMLHttpRequest(); +},_xhr_onreadystatechange:function(d){ +var m=MochiKit.Base; +if(this.readyState==4){ +try{ +this.onreadystatechange=null; +} +catch(e){ +try{ +this.onreadystatechange=m.noop; +} +catch(e){ +} +} +var _295=null; +try{ +_295=this.status; +if(!_295&&m.isNotEmpty(this.responseText)){ +_295=304; +} +} +catch(e){ +} +if(_295==200||_295==304){ +d.callback(this); +}else{ +var err=new MochiKit.Async.XMLHttpRequestError(this,"Request failed"); +if(err.number){ +d.errback(err); +}else{ +d.errback(err); +} +} +} +},_xhr_canceller:function(req){ +try{ +req.onreadystatechange=null; +} +catch(e){ +try{ +req.onreadystatechange=MochiKit.Base.noop; +} +catch(e){ +} +} +req.abort(); +},sendXMLHttpRequest:function(req,_298){ +if(typeof (_298)=="undefined"||_298===null){ +_298=""; +} +var m=MochiKit.Base; +var self=MochiKit.Async; +var d=new self.Deferred(m.partial(self._xhr_canceller,req)); +try{ +req.onreadystatechange=m.bind(self._xhr_onreadystatechange,req,d); +req.send(_298); +} +catch(e){ +try{ +req.onreadystatechange=null; +} +catch(ignore){ +} +d.errback(e); +} +return d; +},doSimpleXMLHttpRequest:function(url){ +var self=MochiKit.Async; +var req=self.getXMLHttpRequest(); +if(arguments.length>1){ +var m=MochiKit.Base; +var qs=m.queryString.apply(null,m.extend(null,arguments,1)); +if(qs){ +url+="?"+qs; +} +} +req.open("GET",url,true); +return self.sendXMLHttpRequest(req); +},loadJSONDoc:function(url){ +var self=MochiKit.Async; +var d=self.doSimpleXMLHttpRequest.apply(self,arguments); +d=d.addCallback(self.evalJSONRequest); +return d; +},wait:function(_301,_302){ +var d=new MochiKit.Async.Deferred(); +var m=MochiKit.Base; +if(typeof (_302)!="undefined"){ +d.addCallback(function(){ +return _302; +}); +} +var _303=setTimeout(m.bind("callback",d),Math.floor(_301*1000)); +d.canceller=function(){ +try{ +clearTimeout(_303); +} +catch(e){ +} +}; +return d; +},callLater:function(_304,func){ +var m=MochiKit.Base; +var _305=m.partial.apply(m,m.extend(null,arguments,1)); +return MochiKit.Async.wait(_304).addCallback(function(res){ +return _305(); +}); +}}); +MochiKit.Async.DeferredLock=function(){ +this.waiting=[]; +this.locked=false; +this.id=this._nextId(); +}; +MochiKit.Async.DeferredLock.prototype={__class__:MochiKit.Async.DeferredLock,acquire:function(){ +d=new MochiKit.Async.Deferred(); +if(this.locked){ +this.waiting.push(d); +}else{ +this.locked=true; +d.callback(this); +} +return d; +},release:function(){ +if(!this.locked){ +throw TypeError("Tried to release an unlocked DeferredLock"); +} +this.locked=false; +if(this.waiting.length>0){ +this.locked=true; +this.waiting.shift().callback(this); +} +},_nextId:MochiKit.Base.counter(),repr:function(){ +var _306; +if(this.locked){ +_306="locked, "+this.waiting.length+" waiting"; +}else{ +_306="unlocked"; +} +return "DeferredLock("+this.id+", "+_306+")"; +},toString:MochiKit.Base.forwardCall("repr")}; +MochiKit.Async.DeferredList=function(list,_308,_309,_310,_311){ +MochiKit.Async.Deferred.apply(this,[_311]); +this.list=list; +var _312=[]; +this.resultList=_312; +this.finishedCount=0; +this.fireOnOneCallback=_308; +this.fireOnOneErrback=_309; +this.consumeErrors=_310; +var cb=MochiKit.Base.bind(this._cbDeferred,this); +for(var i=0;i=0){ +var opt=elem.options[elem.selectedIndex]; +_326.push(name); +_327.push((opt.value)?opt.value:opt.text); +return null; +} +_326.push(name); +_327.push(""); +return null; +}else{ +var opts=elem.options; +if(!opts.length){ +_326.push(name); +_327.push(""); +return null; +} +for(var i=0;i0){ +return node; +} +if(typeof (node)=="number"||typeof (node)=="boolean"){ +node=node.toString(); +} +if(typeof (node)=="string"){ +return self._document.createTextNode(node); +} +if(typeof (node.__dom__)=="function"){ +node=node.__dom__(ctx); +continue; +} +if(typeof (node.dom)=="function"){ +node=node.dom(ctx); +continue; +} +if(typeof (node)=="function"){ +node=node.apply(ctx,[ctx]); +continue; +} +if(im){ +var _342=null; +try{ +_342=iter(node); +} +catch(e){ +} +if(_342){ +return map(_340,_342,_338(ctx)); +} +} +try{ +node=_339.match(node,ctx); +continue; +} +catch(e){ +if(e!=_341){ +throw e; +} +} +return self._document.createTextNode(node.toString()); +} +return undefined; +},setNodeAttribute:function(node,attr,_344){ +var o={}; +o[attr]=_344; +try{ +return MochiKit.DOM.updateNodeAttributes(node,o); +} +catch(e){ +} +return null; +},getNodeAttribute:function(node,attr){ +var self=MochiKit.DOM; +var _345=self.attributeArray.renames[attr]; +node=self.getElement(node); +try{ +if(_345){ +return node[_345]; +} +return node.getAttribute(attr); +} +catch(e){ +} +return null; +},updateNodeAttributes:function(node,_346){ +var elem=node; +var self=MochiKit.DOM; +if(typeof (node)=="string"){ +elem=self.getElement(node); +} +if(_346){ +var _347=MochiKit.Base.updatetree; +if(self.attributeArray.compliant){ +for(var k in _346){ +var v=_346[k]; +if(typeof (v)=="object"&&typeof (elem[k])=="object"){ +_347(elem[k],v); +}else{ +if(k.substring(0,2)=="on"){ +if(typeof (v)=="string"){ +v=new Function(v); +} +elem[k]=v; +}else{ +elem.setAttribute(k,v); +} +} +} +}else{ +var _348=self.attributeArray.renames; +for(k in _346){ +v=_346[k]; +var _349=_348[k]; +if(k=="style"&&typeof (v)=="string"){ +elem.style.cssText=v; +}else{ +if(typeof (_349)=="string"){ +elem[_349]=v; +}else{ +if(typeof (elem[k])=="object"&&typeof (v)=="object"){ +_347(elem[k],v); +}else{ +if(k.substring(0,2)=="on"){ +if(typeof (v)=="string"){ +v=new Function(v); +} +elem[k]=v; +}else{ +elem.setAttribute(k,v); +} +} +} +} +} +} +} +return elem; +},appendChildNodes:function(node){ +var elem=node; +var self=MochiKit.DOM; +if(typeof (node)=="string"){ +elem=self.getElement(node); +} +var _350=[self.coerceToDOM(MochiKit.Base.extend(null,arguments,1),elem)]; +var _351=MochiKit.Base.concat; +while(_350.length){ +var n=_350.shift(); +if(typeof (n)=="undefined"||n===null){ +}else{ +if(typeof (n.nodeType)=="number"){ +elem.appendChild(n); +}else{ +_350=_351(n,_350); +} +} +} +return elem; +},replaceChildNodes:function(node){ +var elem=node; +var self=MochiKit.DOM; +if(typeof (node)=="string"){ +elem=self.getElement(node); +arguments[0]=elem; +} +var _352; +while((_352=elem.firstChild)){ +elem.removeChild(_352); +} +if(arguments.length<2){ +return elem; +}else{ +return self.appendChildNodes.apply(this,arguments); +} +},createDOM:function(name,_353){ +var elem; +var self=MochiKit.DOM; +var m=MochiKit.Base; +if(typeof (_353)=="string"||typeof (_353)=="number"){ +var args=m.extend([name,null],arguments,1); +return arguments.callee.apply(this,args); +} +if(typeof (name)=="string"){ +if(_353&&!self.attributeArray.compliant){ +var _354=""; +if("name" in _353){ +_354+=" name=\""+self.escapeHTML(_353.name)+"\""; +} +if(name=="input"&&"type" in _353){ +_354+=" type=\""+self.escapeHTML(_353.type)+"\""; +} +if(_354){ +name="<"+name+_354+">"; +} +} +elem=self._document.createElement(name); +}else{ +elem=name; +} +if(_353){ +self.updateNodeAttributes(elem,_353); +} +if(arguments.length<=2){ +return elem; +}else{ +var args=m.extend([elem],arguments,2); +return self.appendChildNodes.apply(this,args); +} +},createDOMFunc:function(){ +var m=MochiKit.Base; +return m.partial.apply(this,m.extend([MochiKit.DOM.createDOM],arguments)); +},removeElement:function(elem){ +var e=MochiKit.DOM.getElement(elem); +e.parentNode.removeChild(e); +return e; +},swapDOM:function(dest,src){ +var self=MochiKit.DOM; +dest=self.getElement(dest); +var _357=dest.parentNode; +if(src){ +src=self.getElement(src); +_357.replaceChild(src,dest); +}else{ +_357.removeChild(dest); +} +return src; +},getElement:function(id){ +var self=MochiKit.DOM; +if(arguments.length==1){ +return ((typeof (id)=="string")?self._document.getElementById(id):id); +}else{ +return MochiKit.Base.map(self.getElement,arguments); +} +},getElementsByTagAndClassName:function(_359,_360,_361){ +var self=MochiKit.DOM; +if(typeof (_359)=="undefined"||_359===null){ +_359="*"; +} +if(typeof (_361)=="undefined"||_361===null){ +_361=self._document; +} +_361=self.getElement(_361); +var _362=(_361.getElementsByTagName(_359)||self._document.all); +if(typeof (_360)=="undefined"||_360===null){ +return MochiKit.Base.extend(null,_362); +} +var _363=[]; +for(var i=0;i<_362.length;i++){ +var _364=_362[i]; +var _365=_364.className.split(" "); +for(var j=0;j<_365.length;j++){ +if(_365[j]==_360){ +_363.push(_364); +break; +} +} +} +return _363; +},_newCallStack:function(path,once){ +var rval=function(){ +var _368=arguments.callee.callStack; +for(var i=0;i<_368.length;i++){ +if(_368[i].apply(this,arguments)===false){ +break; +} +} +if(once){ +try{ +this[path]=null; +} +catch(e){ +} +} +}; +rval.callStack=[]; +return rval; +},addToCallStack:function(_369,path,func,once){ +var self=MochiKit.DOM; +var _370=_369[path]; +var _371=_370; +if(!(typeof (_370)=="function"&&typeof (_370.callStack)=="object"&&_370.callStack!==null)){ +_371=self._newCallStack(path,once); +if(typeof (_370)=="function"){ +_371.callStack.push(_370); +} +_369[path]=_371; +} +_371.callStack.push(func); +},addLoadEvent:function(func){ +var self=MochiKit.DOM; +self.addToCallStack(self._window,"onload",func,true); +},focusOnLoad:function(_372){ +var self=MochiKit.DOM; +self.addLoadEvent(function(){ +_372=self.getElement(_372); +if(_372){ +_372.focus(); +} +}); +},setElementClass:function(_373,_374){ +var self=MochiKit.DOM; +var obj=self.getElement(_373); +if(self.attributeArray.compliant){ +obj.setAttribute("class",_374); +}else{ +obj.setAttribute("className",_374); +} +},toggleElementClass:function(_375){ +var self=MochiKit.DOM; +for(var i=1;i/g,">"); +},toHTML:function(dom){ +return MochiKit.DOM.emitHTML(dom).join(""); +},emitHTML:function(dom,lst){ +if(typeof (lst)=="undefined"||lst===null){ +lst=[]; +} +var _391=[dom]; +var self=MochiKit.DOM; +var _392=self.escapeHTML; +var _393=self.attributeArray; +while(_391.length){ +dom=_391.pop(); +if(typeof (dom)=="string"){ +lst.push(dom); +}else{ +if(dom.nodeType==1){ +lst.push("<"+dom.nodeName.toLowerCase()); +var _394=[]; +var _395=_393(dom); +for(var i=0;i<_395.length;i++){ +var a=_395[i]; +_394.push([" ",a.name,"=\"",_392(a.value),"\""]); +} +_394.sort(); +for(i=0;i<_394.length;i++){ +var _396=_394[i]; +for(var j=0;j<_396.length;j++){ +lst.push(_396[j]); +} +} +if(dom.hasChildNodes()){ +lst.push(">"); +_391.push(""); +var _397=dom.childNodes; +for(i=_397.length-1;i>=0;i--){ +_391.push(_397[i]); +} +}else{ +lst.push("/>"); +} +}else{ +if(dom.nodeType==3){ +lst.push(_392(dom.nodeValue)); +} +} +} +} +return lst; +},scrapeText:function(node,_398){ +var rval=[]; +(function(node){ +var cn=node.childNodes; +if(cn){ +for(var i=0;i0){ +var _404=m.filter; +_403=function(node){ +return _404(_403.ignoreAttrFilter,node.attributes); +}; +_403.ignoreAttr={}; +var _405=_402.attributes; +var _406=_403.ignoreAttr; +for(var i=0;i<_405.length;i++){ +var a=_405[i]; +_406[a.name]=a.value; +} +_403.ignoreAttrFilter=function(a){ +return (_403.ignoreAttr[a.name]!=a.value); +}; +_403.compliant=false; +_403.renames={"class":"className","checked":"defaultChecked","usemap":"useMap","for":"htmlFor","readonly":"readOnly"}; +}else{ +_403=function(node){ +return node.attributes; +}; +_403.compliant=true; +_403.renames={}; +} +this.attributeArray=_403; +var _407=function(_408,arr){ +var _409=arr[1].split("."); +var str=""; +var obj={}; +str+="if (!MochiKit."+_409[1]+") { throw new Error(\""; +str+="This function has been deprecated and depends on MochiKit."; +str+=_409[1]+".\");}"; +str+="return MochiKit."+_409[1]+"."+arr[0]; +str+=".apply(this, arguments);"; +obj[_409[2]]=new Function(str); +MochiKit.Base.update(MochiKit[_408],obj); +}; +for(var i;i<&-]/g,"_"); +var name=uid+"_"+url; +var nwin=win.open("",name,"dependent,resizable,height=200"); +if(!nwin){ +alert("Not able to open debugging window due to pop-up blocking."); +return undefined; +} +nwin.document.write(""+"[MochiKit.LoggingPane]"+""); +nwin.document.close(); +nwin.document.title+=" "+win.document.title; +win=nwin; +} +var doc=win.document; +this.doc=doc; +var _444=doc.getElementById(uid); +var _445=!!_444; +if(_444&&typeof (_444.loggingPane)!="undefined"){ +_444.loggingPane.logger=this.logger; +_444.loggingPane.buildAndApplyFilter(); +return _444.loggingPane; +} +if(_445){ +var _446; +while((_446=_444.firstChild)){ +_444.removeChild(_446); +} +}else{ +_444=doc.createElement("div"); +_444.id=uid; +} +_444.loggingPane=this; +var _447=doc.createElement("input"); +var _448=doc.createElement("input"); +var _449=doc.createElement("button"); +var _450=doc.createElement("button"); +var _451=doc.createElement("button"); +var _452=doc.createElement("button"); +var _453=doc.createElement("div"); +var _454=doc.createElement("div"); +var _455=uid+"_Listener"; +this.colorTable=_441(this.colorTable); +var _456=[]; +var _457=null; +var _458=function(msg){ +var _459=msg.level; +if(typeof (_459)=="number"){ +_459=MochiKit.Logging.LogLevel[_459]; +} +return _459; +}; +var _460=function(msg){ +return msg.info.join(" "); +}; +var _461=bind(function(msg){ +var _462=_458(msg); +var text=_460(msg); +var c=this.colorTable[_462]; +var p=doc.createElement("span"); +p.className="MochiKit-LogMessage MochiKit-LogLevel-"+_462; +p.appendChild(doc.createTextNode(_462+": "+text)); +_454.appendChild(p); +_454.appendChild(doc.createElement("br")); +if(_453.offsetHeight>_453.scrollHeight){ +_453.scrollTop=0; +}else{ +_453.scrollTop=_453.scrollHeight; +} +},this); +var _464=function(msg){ +_456[_456.length]=msg; +_461(msg); +}; +var _465=function(){ +var _466,infore; +try{ +_466=new RegExp(_447.value); +infore=new RegExp(_448.value); +} +catch(e){ +logDebug("Error in filter regex: "+e.message); +return null; +} +return function(msg){ +return (_466.test(_458(msg))&&infore.test(_460(msg))); +}; +}; +var _467=function(){ +while(_454.firstChild){ +_454.removeChild(_454.firstChild); +} +}; +var _468=function(){ +_456=[]; +_467(); +}; +var _469=bind(function(){ +if(this.closed){ +return; +} +this.closed=true; +if(MochiKit.LoggingPane._loggingPane==this){ +MochiKit.LoggingPane._loggingPane=null; +} +this.logger.removeListener(_455); +_444.loggingPane=null; +if(_437){ +_444.parentNode.removeChild(_444); +}else{ +this.win.close(); +} +},this); +var _470=function(){ +_467(); +for(var i=0;i<_456.length;i++){ +var msg=_456[i]; +if(_457===null||_457(msg)){ +_461(msg); +} +} +}; +this.buildAndApplyFilter=function(){ +_457=_465(); +_470(); +this.logger.removeListener(_455); +this.logger.addListener(_455,_457,_464); +}; +var _471=bind(function(){ +_456=this.logger.getMessages(); +_470(); +},this); +var _472=bind(function(_473){ +_473=_473||window.event; +key=_473.which||_473.keyCode; +if(key==13){ +this.buildAndApplyFilter(); +} +},this); +var _474="display: block; z-index: 1000; left: 0px; bottom: 0px; position: fixed; width: 100%; background-color: white; font: "+this.logFont; +if(_437){ +_474+="; height: 10em; border-top: 2px solid black"; +}else{ +_474+="; height: 100%;"; +} +_444.style.cssText=_474; +if(!_445){ +doc.body.appendChild(_444); +} +_474={"cssText":"width: 33%; display: inline; font: "+this.logFont}; +_440(_447,{"value":"FATAL|ERROR|WARNING|INFO|DEBUG","onkeypress":_472,"style":_474}); +_444.appendChild(_447); +_440(_448,{"value":".*","onkeypress":_472,"style":_474}); +_444.appendChild(_448); +_474="width: 8%; display:inline; font: "+this.logFont; +_449.appendChild(doc.createTextNode("Filter")); +_449.onclick=bind("buildAndApplyFilter",this); +_449.style.cssText=_474; +_444.appendChild(_449); +_450.appendChild(doc.createTextNode("Load")); +_450.onclick=_471; +_450.style.cssText=_474; +_444.appendChild(_450); +_451.appendChild(doc.createTextNode("Clear")); +_451.onclick=_468; +_451.style.cssText=_474; +_444.appendChild(_451); +_452.appendChild(doc.createTextNode("Close")); +_452.onclick=_469; +_452.style.cssText=_474; +_444.appendChild(_452); +_453.style.cssText="overflow: auto; width: 100%"; +_454.style.cssText="width: 100%; height: "+(_437?"8em":"100%"); +_453.appendChild(_454); +_444.appendChild(_453); +this.buildAndApplyFilter(); +_471(); +if(_437){ +this.win=undefined; +}else{ +this.win=win; +} +this.inline=_437; +this.closePane=_469; +this.closed=false; +return this; +}; +MochiKit.LoggingPane.LoggingPane.prototype={"logFont":"8pt Verdana,sans-serif","colorTable":{"ERROR":"red","FATAL":"darkred","WARNING":"blue","INFO":"black","DEBUG":"green"}}; +MochiKit.LoggingPane.EXPORT_OK=["LoggingPane"]; +MochiKit.LoggingPane.EXPORT=["createLoggingPane"]; +MochiKit.LoggingPane.__new__=function(){ +this.EXPORT_TAGS={":common":this.EXPORT,":all":MochiKit.Base.concat(this.EXPORT,this.EXPORT_OK)}; +MochiKit.Base.nameFunctions(this); +MochiKit.LoggingPane._loggingPane=null; +}; +MochiKit.LoggingPane.__new__(); +MochiKit.Base._exportSymbols(this,MochiKit.LoggingPane); +if(typeof (dojo)!="undefined"){ +dojo.provide("MochiKit.Color"); +dojo.require("MochiKit.Base"); +dojo.require("MochiKit.DOM"); +dojo.require("MochiKit.Style"); +} +if(typeof (JSAN)!="undefined"){ +JSAN.use("MochiKit.Base",[]); +JSAN.use("MochiKit.DOM",[]); +JSAN.use("MochiKit.Style",[]); +} +try{ +if(typeof (MochiKit.Base)=="undefined"){ +throw ""; +} +} +catch(e){ +throw "MochiKit.Color depends on MochiKit.Base"; +} +try{ +if(typeof (MochiKit.Base)=="undefined"){ +throw ""; +} +} +catch(e){ +throw "MochiKit.Color depends on MochiKit.DOM"; +} +try{ +if(typeof (MochiKit.Base)=="undefined"){ +throw ""; +} +} +catch(e){ +throw "MochiKit.Color depends on MochiKit.Style"; +} +if(typeof (MochiKit.Color)=="undefined"){ +MochiKit.Color={}; +} +MochiKit.Color.NAME="MochiKit.Color"; +MochiKit.Color.VERSION="1.4"; +MochiKit.Color.__repr__=function(){ +return "["+this.NAME+" "+this.VERSION+"]"; +}; +MochiKit.Color.toString=function(){ +return this.__repr__(); +}; +MochiKit.Color.Color=function(red,_476,blue,_478){ +if(typeof (_478)=="undefined"||_478===null){ +_478=1; +} +this.rgb={r:red,g:_476,b:blue,a:_478}; +}; +MochiKit.Color.Color.prototype={__class__:MochiKit.Color.Color,colorWithAlpha:function(_479){ +var rgb=this.rgb; +var m=MochiKit.Color; +return m.Color.fromRGB(rgb.r,rgb.g,rgb.b,_479); +},colorWithHue:function(hue){ +var hsl=this.asHSL(); +hsl.h=hue; +var m=MochiKit.Color; +return m.Color.fromHSL(hsl); +},colorWithSaturation:function(_483){ +var hsl=this.asHSL(); +hsl.s=_483; +var m=MochiKit.Color; +return m.Color.fromHSL(hsl); +},colorWithLightness:function(_484){ +var hsl=this.asHSL(); +hsl.l=_484; +var m=MochiKit.Color; +return m.Color.fromHSL(hsl); +},darkerColorWithLevel:function(_485){ +var hsl=this.asHSL(); +hsl.l=Math.max(hsl.l-_485,0); +var m=MochiKit.Color; +return m.Color.fromHSL(hsl); +},lighterColorWithLevel:function(_486){ +var hsl=this.asHSL(); +hsl.l=Math.min(hsl.l+_486,1); +var m=MochiKit.Color; +return m.Color.fromHSL(hsl); +},blendedColor:function(_487,_488){ +if(typeof (_488)=="undefined"||_488===null){ +_488=0.5; +} +var sf=1-_488; +var s=this.rgb; +var d=_487.rgb; +var df=_488; +return MochiKit.Color.Color.fromRGB((s.r*sf)+(d.r*df),(s.g*sf)+(d.g*df),(s.b*sf)+(d.b*df),(s.a*sf)+(d.a*df)); +},compareRGB:function(_491){ +var a=this.asRGB(); +var b=_491.asRGB(); +return MochiKit.Base.compare([a.r,a.g,a.b,a.a],[b.r,b.g,b.b,b.a]); +},isLight:function(){ +return this.asHSL().b>0.5; +},isDark:function(){ +return (!this.isLight()); +},toHSLString:function(){ +var c=this.asHSL(); +var ccc=MochiKit.Color.clampColorComponent; +var rval=this._hslString; +if(!rval){ +var mid=(ccc(c.h,360).toFixed(0)+","+ccc(c.s,100).toPrecision(4)+"%"+","+ccc(c.l,100).toPrecision(4)+"%"); +var a=c.a; +if(a>=1){ +a=1; +rval="hsl("+mid+")"; +}else{ +if(a<=0){ +a=0; +} +rval="hsla("+mid+","+a+")"; +} +this._hslString=rval; +} +return rval; +},toRGBString:function(){ +var c=this.rgb; +var ccc=MochiKit.Color.clampColorComponent; +var rval=this._rgbString; +if(!rval){ +var mid=(ccc(c.r,255).toFixed(0)+","+ccc(c.g,255).toFixed(0)+","+ccc(c.b,255).toFixed(0)); +if(c.a!=1){ +rval="rgba("+mid+","+c.a+")"; +}else{ +rval="rgb("+mid+")"; +} +this._rgbString=rval; +} +return rval; +},asRGB:function(){ +return MochiKit.Base.clone(this.rgb); +},toHexString:function(){ +var m=MochiKit.Color; +var c=this.rgb; +var ccc=MochiKit.Color.clampColorComponent; +var rval=this._hexString; +if(!rval){ +rval=("#"+m.toColorPart(ccc(c.r,255))+m.toColorPart(ccc(c.g,255))+m.toColorPart(ccc(c.b,255))); +this._hexString=rval; +} +return rval; +},asHSV:function(){ +var hsv=this.hsv; +var c=this.rgb; +if(typeof (hsv)=="undefined"||hsv===null){ +hsv=MochiKit.Color.rgbToHSV(this.rgb); +this.hsv=hsv; +} +return MochiKit.Base.clone(hsv); +},asHSL:function(){ +var hsl=this.hsl; +var c=this.rgb; +if(typeof (hsl)=="undefined"||hsl===null){ +hsl=MochiKit.Color.rgbToHSL(this.rgb); +this.hsl=hsl; +} +return MochiKit.Base.clone(hsl); +},toString:function(){ +return this.toRGBString(); +},repr:function(){ +var c=this.rgb; +var col=[c.r,c.g,c.b,c.a]; +return this.__class__.NAME+"("+col.join(", ")+")"; +}}; +MochiKit.Base.update(MochiKit.Color.Color,{fromRGB:function(red,_496,blue,_497){ +var _498=MochiKit.Color.Color; +if(arguments.length==1){ +var rgb=red; +red=rgb.r; +_496=rgb.g; +blue=rgb.b; +if(typeof (rgb.a)=="undefined"){ +_497=undefined; +}else{ +_497=rgb.a; +} +} +return new _498(red,_496,blue,_497); +},fromHSL:function(hue,_499,_500,_501){ +var m=MochiKit.Color; +return m.Color.fromRGB(m.hslToRGB.apply(m,arguments)); +},fromHSV:function(hue,_502,_503,_504){ +var m=MochiKit.Color; +return m.Color.fromRGB(m.hsvToRGB.apply(m,arguments)); +},fromName:function(name){ +var _505=MochiKit.Color.Color; +if(name.charAt(0)=="\""){ +name=name.substr(1,name.length-2); +} +var _506=_505._namedColors[name.toLowerCase()]; +if(typeof (_506)=="string"){ +return _505.fromHexString(_506); +}else{ +if(name=="transparent"){ +return _505.transparentColor(); +} +} +return null; +},fromString:function(_507){ +var self=MochiKit.Color.Color; +var _508=_507.substr(0,3); +if(_508=="rgb"){ +return self.fromRGBString(_507); +}else{ +if(_508=="hsl"){ +return self.fromHSLString(_507); +}else{ +if(_507.charAt(0)=="#"){ +return self.fromHexString(_507); +} +} +} +return self.fromName(_507); +},fromHexString:function(_509){ +if(_509.charAt(0)=="#"){ +_509=_509.substring(1); +} +var _510=[]; +var i,hex; +if(_509.length==3){ +for(i=0;i<3;i++){ +hex=_509.substr(i,1); +_510.push(parseInt(hex+hex,16)/255); +} +}else{ +for(i=0;i<6;i+=2){ +hex=_509.substr(i,2); +_510.push(parseInt(hex,16)/255); +} +} +var _511=MochiKit.Color.Color; +return _511.fromRGB.apply(_511,_510); +},_fromColorString:function(pre,_513,_514,_515){ +if(_515.indexOf(pre)===0){ +_515=_515.substring(_515.indexOf("(",3)+1,_515.length-1); +} +var _516=_515.split(/\s*,\s*/); +var _517=[]; +for(var i=0;i<_516.length;i++){ +var c=_516[i]; +var val; +var _518=c.substring(c.length-3); +if(c.charAt(c.length-1)=="%"){ +val=0.01*parseFloat(c.substring(0,c.length-1)); +}else{ +if(_518=="deg"){ +val=parseFloat(c)/360; +}else{ +if(_518=="rad"){ +val=parseFloat(c)/(Math.PI*2); +}else{ +val=_514[i]*parseFloat(c); +} +} +} +_517.push(val); +} +return this[_513].apply(this,_517); +},fromComputedStyle:function(elem,_519){ +var d=MochiKit.DOM; +var cls=MochiKit.Color.Color; +for(elem=d.getElement(elem);elem;elem=elem.parentNode){ +var _520=MochiKit.Style.computedStyle.apply(d,arguments); +if(!_520){ +continue; +} +var _521=cls.fromString(_520); +if(!_521){ +break; +} +if(_521.asRGB().a>0){ +return _521; +} +} +return null; +},fromBackground:function(elem){ +var cls=MochiKit.Color.Color; +return cls.fromComputedStyle(elem,"backgroundColor","background-color")||cls.whiteColor(); +},fromText:function(elem){ +var cls=MochiKit.Color.Color; +return cls.fromComputedStyle(elem,"color","color")||cls.blackColor(); +},namedColors:function(){ +return MochiKit.Base.clone(MochiKit.Color.Color._namedColors); +}}); +MochiKit.Base.update(MochiKit.Color,{clampColorComponent:function(v,_522){ +v*=_522; +if(v<0){ +return 0; +}else{ +if(v>_522){ +return _522; +}else{ +return v; +} +} +},_hslValue:function(n1,n2,hue){ +if(hue>6){ +hue-=6; +}else{ +if(hue<0){ +hue+=6; +} +} +var val; +if(hue<1){ +val=n1+(n2-n1)*hue; +}else{ +if(hue<3){ +val=n2; +}else{ +if(hue<4){ +val=n1+(n2-n1)*(4-hue); +}else{ +val=n1; +} +} +} +return val; +},hsvToRGB:function(hue,_525,_526,_527){ +if(arguments.length==1){ +var hsv=hue; +hue=hsv.h; +_525=hsv.s; +_526=hsv.v; +_527=hsv.a; +} +var red; +var _528; +var blue; +if(_525===0){ +red=0; +_528=0; +blue=0; +}else{ +var i=Math.floor(hue*6); +var f=(hue*6)-i; +var p=_526*(1-_525); +var q=_526*(1-(_525*f)); +var t=_526*(1-(_525*(1-f))); +switch(i){ +case 1: +red=q; +_528=_526; +blue=p; +break; +case 2: +red=p; +_528=_526; +blue=t; +break; +case 3: +red=p; +_528=q; +blue=_526; +break; +case 4: +red=t; +_528=p; +blue=_526; +break; +case 5: +red=_526; +_528=p; +blue=q; +break; +case 6: +case 0: +red=_526; +_528=t; +blue=p; +break; +} +} +return {r:red,g:_528,b:blue,a:_527}; +},hslToRGB:function(hue,_530,_531,_532){ +if(arguments.length==1){ +var hsl=hue; +hue=hsl.h; +_530=hsl.s; +_531=hsl.l; +_532=hsl.a; +} +var red; +var _533; +var blue; +if(_530===0){ +red=_531; +_533=_531; +blue=_531; +}else{ +var m2; +if(_531<=0.5){ +m2=_531*(1+_530); +}else{ +m2=_531+_530-(_531*_530); +} +var m1=(2*_531)-m2; +var f=MochiKit.Color._hslValue; +var h6=hue*6; +red=f(m1,m2,h6+2); +_533=f(m1,m2,h6); +blue=f(m1,m2,h6-2); +} +return {r:red,g:_533,b:blue,a:_532}; +},rgbToHSV:function(red,_537,blue,_538){ +if(arguments.length==1){ +var rgb=red; +red=rgb.r; +_537=rgb.g; +blue=rgb.b; +_538=rgb.a; +} +var max=Math.max(Math.max(red,_537),blue); +var min=Math.min(Math.min(red,_537),blue); +var hue; +var _541; +var _542=max; +if(min==max){ +hue=0; +_541=0; +}else{ +var _543=(max-min); +_541=_543/max; +if(red==max){ +hue=(_537-blue)/_543; +}else{ +if(_537==max){ +hue=2+((blue-red)/_543); +}else{ +hue=4+((red-_537)/_543); +} +} +hue/=6; +if(hue<0){ +hue+=1; +} +if(hue>1){ +hue-=1; +} +} +return {h:hue,s:_541,v:_542,a:_538}; +},rgbToHSL:function(red,_544,blue,_545){ +if(arguments.length==1){ +var rgb=red; +red=rgb.r; +_544=rgb.g; +blue=rgb.b; +_545=rgb.a; +} +var max=Math.max(red,Math.max(_544,blue)); +var min=Math.min(red,Math.min(_544,blue)); +var hue; +var _546; +var _547=(max+min)/2; +var _548=max-min; +if(_548===0){ +hue=0; +_546=0; +}else{ +if(_547<=0.5){ +_546=_548/(max+min); +}else{ +_546=_548/(2-max-min); +} +if(red==max){ +hue=(_544-blue)/_548; +}else{ +if(_544==max){ +hue=2+((blue-red)/_548); +}else{ +hue=4+((red-_544)/_548); +} +} +hue/=6; +if(hue<0){ +hue+=1; +} +if(hue>1){ +hue-=1; +} +} +return {h:hue,s:_546,l:_547,a:_545}; +},toColorPart:function(num){ +num=Math.round(num); +var _549=num.toString(16); +if(num<16){ +return "0"+_549; +} +return _549; +},__new__:function(){ +var m=MochiKit.Base; +this.Color.fromRGBString=m.bind(this.Color._fromColorString,this.Color,"rgb","fromRGB",[1/255,1/255,1/255,1]); +this.Color.fromHSLString=m.bind(this.Color._fromColorString,this.Color,"hsl","fromHSL",[1/360,0.01,0.01,1]); +var _550=1/3; +var _551={black:[0,0,0],blue:[0,0,1],brown:[0.6,0.4,0.2],cyan:[0,1,1],darkGray:[_550,_550,_550],gray:[0.5,0.5,0.5],green:[0,1,0],lightGray:[2*_550,2*_550,2*_550],magenta:[1,0,1],orange:[1,0.5,0],purple:[0.5,0,0.5],red:[1,0,0],transparent:[0,0,0,0],white:[1,1,1],yellow:[1,1,0]}; +var _552=function(name,r,g,b,a){ +var rval=this.fromRGB(r,g,b,a); +this[name]=function(){ +return rval; +}; +return rval; +}; +for(var k in _551){ +var name=k+"Color"; +var _554=m.concat([_552,this.Color,name],_551[k]); +this.Color[name]=m.bind.apply(null,_554); +} +var _555=function(){ +for(var i=0;i1){ +var src=MochiKit.DOM.getElement(arguments[0]); +var sig=arguments[1]; +var obj=arguments[2]; +var func=arguments[3]; +for(var i=_571.length-1;i>=0;i--){ +var o=_571[i]; +if(o[0]===src&&o[1]===sig&&o[4]===obj&&o[5]===func){ +self._disconnect(o); +_571.splice(i,1); +return true; +} +} +}else{ +var idx=m.findIdentical(_571,_570); +if(idx>=0){ +self._disconnect(_570); +_571.splice(idx,1); +return true; +} +} +return false; +},disconnectAll:function(src,sig){ +src=MochiKit.DOM.getElement(src); +var m=MochiKit.Base; +var _572=m.flattenArguments(m.extend(null,arguments,1)); +var self=MochiKit.Signal; +var _573=self._disconnect; +var _574=self._observers; +if(_572.length===0){ +for(var i=_574.length-1;i>=0;i--){ +var _575=_574[i]; +if(_575[0]===src){ +_573(_575); +_574.splice(i,1); +} +} +}else{ +var sigs={}; +for(var i=0;i<_572.length;i++){ +sigs[_572[i]]=true; +} +for(var i=_574.length-1;i>=0;i--){ +var _575=_574[i]; +if(_575[0]===src&&_575[1] in sigs){ +_573(_575); +_574.splice(i,1); +} +} +} +},signal:function(src,sig){ +var _577=MochiKit.Signal._observers; +src=MochiKit.DOM.getElement(src); +var args=MochiKit.Base.extend(null,arguments,2); +var _578=[]; +for(var i=0;i<_577.length;i++){ +var _579=_577[i]; +if(_579[0]===src&&_579[1]===sig){ +try{ +_579[2].apply(src,args); +} +catch(e){ +_578.push(e); +} +} +} +if(_578.length==1){ +throw _578[0]; +}else{ +if(_578.length>1){ +var e=new Error("Multiple errors thrown in handling 'sig', see errors property"); +e.errors=_578; +throw e; +} +} +}}); +MochiKit.Signal.EXPORT_OK=[]; +MochiKit.Signal.EXPORT=["connect","disconnect","signal","disconnectAll"]; +MochiKit.Signal.__new__=function(win){ +var m=MochiKit.Base; +this._document=document; +this._window=win; +try{ +this.connect(window,"onunload",this._unloadCache); +} +catch(e){ +} +this.EXPORT_TAGS={":common":this.EXPORT,":all":m.concat(this.EXPORT,this.EXPORT_OK)}; +m.nameFunctions(this); +}; +MochiKit.Signal.__new__(this); +if(MochiKit.__export__){ +connect=MochiKit.Signal.connect; +disconnect=MochiKit.Signal.disconnect; +disconnectAll=MochiKit.Signal.disconnectAll; +signal=MochiKit.Signal.signal; +} +MochiKit.Base._exportSymbols(this,MochiKit.Signal); +if(typeof (dojo)!="undefined"){ +dojo.provide("MochiKit.Visual"); +dojo.require("MochiKit.Base"); +dojo.require("MochiKit.DOM"); +dojo.require("MochiKit.Style"); +dojo.require("MochiKit.Color"); +dojo.require("MochiKit.Iter"); +} +if(typeof (JSAN)!="undefined"){ +JSAN.use("MochiKit.Base",[]); +JSAN.use("MochiKit.DOM",[]); +JSAN.use("MochiKit.Style",[]); +JSAN.use("MochiKit.Color",[]); +JSAN.use("MochiKit.Iter",[]); +} +try{ +if(typeof (MochiKit.Base)==="undefined"||typeof (MochiKit.DOM)==="undefined"||typeof (MochiKit.Style)==="undefined"||typeof (MochiKit.Color)==="undefined"||typeof (MochiKit.Iter)==="undefined"){ +throw ""; +} +} +catch(e){ +throw "MochiKit.Visual depends on MochiKit.Base, MochiKit.DOM, MochiKit.Style, MochiKit.Color and MochiKit.Iter!"; +} +if(typeof (MochiKit.Visual)=="undefined"){ +MochiKit.Visual={}; +} +MochiKit.Visual.NAME="MochiKit.Visual"; +MochiKit.Visual.VERSION="1.4"; +MochiKit.Visual.__repr__=function(){ +return "["+this.NAME+" "+this.VERSION+"]"; +}; +MochiKit.Visual.toString=function(){ +return this.__repr__(); +}; +MochiKit.Visual._RoundCorners=function(e,_580){ +e=MochiKit.DOM.getElement(e); +this._setOptions(_580); +if(this.options.__unstable__wrapElement){ +e=this._doWrap(e); +} +var _581=this.options.color; +var C=MochiKit.Color.Color; +if(this.options.color==="fromElement"){ +_581=C.fromBackground(e); +}else{ +if(!(_581 instanceof C)){ +_581=C.fromString(_581); +} +} +this.isTransparent=(_581.asRGB().a<=0); +var _583=this.options.bgColor; +if(this.options.bgColor==="fromParent"){ +_583=C.fromBackground(e.offsetParent); +}else{ +if(!(_583 instanceof C)){ +_583=C.fromString(_583); +} +} +this._roundCornersImpl(e,_581,_583); +}; +MochiKit.Visual._RoundCorners.prototype={_doWrap:function(e){ +var _584=e.parentNode; +var doc=MochiKit.DOM.currentDocument(); +if(typeof (doc.defaultView)==="undefined"||doc.defaultView===null){ +return e; +} +var _585=doc.defaultView.getComputedStyle(e,null); +if(typeof (_585)==="undefined"||_585===null){ +return e; +} +var _586=MochiKit.DOM.DIV({"style":{display:"block",marginTop:_585.getPropertyValue("padding-top"),marginRight:_585.getPropertyValue("padding-right"),marginBottom:_585.getPropertyValue("padding-bottom"),marginLeft:_585.getPropertyValue("padding-left"),padding:"0px"}}); +_586.innerHTML=e.innerHTML; +e.innerHTML=""; +e.appendChild(_586); +return e; +},_roundCornersImpl:function(e,_587,_588){ +if(this.options.border){ +this._renderBorder(e,_588); +} +if(this._isTopRounded()){ +this._roundTopCorners(e,_587,_588); +} +if(this._isBottomRounded()){ +this._roundBottomCorners(e,_587,_588); +} +},_renderBorder:function(el,_590){ +var _591="1px solid "+this._borderColor(_590); +var _592="border-left: "+_591; +var _593="border-right: "+_591; +var _594="style='"+_592+";"+_593+"'"; +el.innerHTML="
"+el.innerHTML+"
"; +},_roundTopCorners:function(el,_595,_596){ +var _597=this._createCorner(_596); +for(var i=0;i=0;i--){ +_600.appendChild(this._createCornerSlice(_598,_599,i,"bottom")); +} +el.style.paddingBottom=0; +el.appendChild(_600); +},_createCorner:function(_601){ +var dom=MochiKit.DOM; +return dom.DIV({style:{backgroundColor:_601.toString()}}); +},_createCornerSlice:function(_602,_603,n,_604){ +var _605=MochiKit.DOM.SPAN(); +var _606=_605.style; +_606.backgroundColor=_602.toString(); +_606.display="block"; +_606.height="1px"; +_606.overflow="hidden"; +_606.fontSize="1px"; +var _607=this._borderColor(_602,_603); +if(this.options.border&&n===0){ +_606.borderTopStyle="solid"; +_606.borderTopWidth="1px"; +_606.borderLeftWidth="0px"; +_606.borderRightWidth="0px"; +_606.borderBottomWidth="0px"; +_606.height="0px"; +_606.borderColor=_607.toString(); +}else{ +if(_607){ +_606.borderColor=_607.toString(); +_606.borderStyle="solid"; +_606.borderWidth="0px 1px"; +} +} +if(!this.options.compact&&(n==(this.options.numSlices-1))){ +_606.height="2px"; +} +this._setMargin(_605,n,_604); +this._setBorder(_605,n,_604); +return _605; +},_setOptions:function(_608){ +this.options={corners:"all",color:"fromElement",bgColor:"fromParent",blend:true,border:false,compact:false,__unstable__wrapElement:false}; +MochiKit.Base.update(this.options,_608); +this.options.numSlices=(this.options.compact?2:4); +},_whichSideTop:function(){ +var _609=this.options.corners; +if(this._hasString(_609,"all","top")){ +return ""; +} +var _610=(_609.indexOf("tl")!=-1); +var _611=(_609.indexOf("tr")!=-1); +if(_610&&_611){ +return ""; +} +if(_610){ +return "left"; +} +if(_611){ +return "right"; +} +return ""; +},_whichSideBottom:function(){ +var _612=this.options.corners; +if(this._hasString(_612,"all","bottom")){ +return ""; +} +var _613=(_612.indexOf("bl")!=-1); +var _614=(_612.indexOf("br")!=-1); +if(_613&&_614){ +return ""; +} +if(_613){ +return "left"; +} +if(_614){ +return "right"; +} +return ""; +},_borderColor:function(_615,_616){ +if(_615=="transparent"){ +return _616; +}else{ +if(this.options.border){ +return this.options.border; +}else{ +if(this.options.blend){ +return _616.blendedColor(_615); +} +} +} +return ""; +},_setMargin:function(el,n,_617){ +var _618=this._marginSize(n)+"px"; +var _619=(_617=="top"?this._whichSideTop():this._whichSideBottom()); +var _620=el.style; +if(_619=="left"){ +_620.marginLeft=_618; +_620.marginRight="0px"; +}else{ +if(_619=="right"){ +_620.marginRight=_618; +_620.marginLeft="0px"; +}else{ +_620.marginLeft=_618; +_620.marginRight=_618; +} +} +},_setBorder:function(el,n,_621){ +var _622=this._borderSize(n)+"px"; +var _623=(_621=="top"?this._whichSideTop():this._whichSideBottom()); +var _624=el.style; +if(_623=="left"){ +_624.borderLeftWidth=_622; +_624.borderRightWidth="0px"; +}else{ +if(_623=="right"){ +_624.borderRightWidth=_622; +_624.borderLeftWidth="0px"; +}else{ +_624.borderLeftWidth=_622; +_624.borderRightWidth=_622; +} +} +},_marginSize:function(n){ +if(this.isTransparent){ +return 0; +} +var o=this.options; +if(o.compact&&o.blend){ +var _625=[1,0]; +return _625[n]; +}else{ +if(o.compact){ +var _626=[2,1]; +return _626[n]; +}else{ +if(o.blend){ +var _627=[3,2,1,0]; +return _627[n]; +}else{ +var _628=[5,3,2,1]; +return _628[n]; +} +} +} +},_borderSize:function(n){ +var o=this.options; +var _629; +if(o.compact&&(o.blend||this.isTransparent)){ +return 1; +}else{ +if(o.compact){ +_629=[1,0]; +}else{ +if(o.blend){ +_629=[2,1,1,1]; +}else{ +if(o.border){ +_629=[0,2,0,0]; +}else{ +if(this.isTransparent){ +_629=[5,3,2,1]; +}else{ +return 0; +} +} +} +} +} +return _629[n]; +},_hasString:function(str){ +for(var i=1;i=(_654||i)){ +_654=i; +} +}); +_652=_654||_652; +break; +} +_651.startOn+=_652; +_651.finishOn+=_652; +if(!_651.options.queue.limit||this.effects.length<_651.options.queue.limit){ +this.effects.push(_651); +} +if(!this.interval){ +this.interval=setInterval(MochiKit.Base.bind(this.loop,this),40); +} +},remove:function(_655){ +this.effects=MochiKit.Base.filter(function(e){ +return e!=_655; +},this.effects); +if(this.effects.length==0){ +clearInterval(this.interval); +this.interval=null; +} +},loop:function(){ +var _656=new Date().getTime(); +MochiKit.Iter.forEach(this.effects,function(_657){ +_657.loop(_656); +}); +}}); +MochiKit.Visual.Queues={instances:{},get:function(_658){ +if(typeof (_658)!="string"){ +return _658; +} +if(!this.instances[_658]){ +this.instances[_658]=new MochiKit.Visual.ScopedQueue(); +} +return this.instances[_658]; +}}; +MochiKit.Visual.Queue=MochiKit.Visual.Queues.get("global"); +MochiKit.Visual.DefaultOptions={transition:MochiKit.Visual.Transitions.sinoidal,duration:1,fps:25,sync:false,from:0,to:1,delay:0,queue:"parallel"}; +MochiKit.Visual.Base=function(){ +}; +MochiKit.Visual.Base.prototype={__class__:MochiKit.Visual.Base,start:function(_659){ +var v=MochiKit.Visual; +this.options=MochiKit.Base.setdefault(_659||{},v.DefaultOptions); +this.currentFrame=0; +this.state="idle"; +this.startOn=this.options.delay*1000; +this.finishOn=this.startOn+(this.options.duration*1000); +this.event("beforeStart"); +if(!this.options.sync){ +v.Queues.get(typeof (this.options.queue)=="string"?"global":this.options.queue.scope).add(this); +} +},loop:function(_660){ +if(_660>=this.startOn){ +if(_660>=this.finishOn){ +this.render(1); +this.cancel(); +this.event("beforeFinish"); +this.finish(); +this.event("afterFinish"); +return; +} +var pos=(_660-this.startOn)/(this.finishOn-this.startOn); +var _661=Math.round(pos*this.options.fps*this.options.duration); +if(_661>this.currentFrame){ +this.render(pos); +this.currentFrame=_661; +} +} +},render:function(pos){ +if(this.state=="idle"){ +this.state="running"; +this.event("beforeSetup"); +this.setup(); +this.event("afterSetup"); +} +if(this.state=="running"){ +if(this.options.transition){ +pos=this.options.transition(pos); +} +pos*=(this.options.to-this.options.from); +pos+=this.options.from; +this.event("beforeUpdate"); +this.update(pos); +this.event("afterUpdate"); +} +},cancel:function(){ +if(!this.options.sync){ +MochiKit.Visual.Queues.get(typeof (this.options.queue)=="string"?"global":this.options.queue.scope).remove(this); +} +this.state="finished"; +},setup:function(){ +},finish:function(){ +},update:function(_662){ +},event:function(_663){ +if(this.options[_663+"Internal"]){ +this.options[_663+"Internal"](this); +} +if(this.options[_663]){ +this.options[_663](this); +} +},repr:function(){ +return "["+this.__class__.NAME+", options:"+MochiKit.Base.repr(this.options)+"]"; +}}; +MochiKit.Visual.Parallel=function(_664,_665){ +this.__init__(_664,_665); +}; +MochiKit.Visual.Parallel.prototype=new MochiKit.Visual.Base(); +MochiKit.Base.update(MochiKit.Visual.Parallel.prototype,{__init__:function(_666,_667){ +this.effects=_666||[]; +this.start(_667); +},update:function(_668){ +MochiKit.Iter.forEach(this.effects,function(_669){ +_669.render(_668); +}); +},finish:function(){ +MochiKit.Iter.forEach(this.effects,function(_670){ +_670.render(1); +_670.cancel(); +_670.event("beforeFinish"); +_670.finish(); +_670.event("afterFinish"); +}); +}}); +MochiKit.Visual.Opacity=function(_671,_672){ +this.__init__(_671,_672); +}; +MochiKit.Visual.Opacity.prototype=new MochiKit.Visual.Base(); +MochiKit.Base.update(MochiKit.Visual.Opacity.prototype,{__init__:function(_673,_674){ +var b=MochiKit.Base; +var d=MochiKit.DOM; +this.element=d.getElement(_673); +if(b.isIE()&&(!this.element.currentStyle.hasLayout)){ +d.setStyle(this.element,{zoom:1}); +} +_674=b.update({from:d.getOpacity(this.element)||0,to:1},_674||{}); +this.start(_674); +},update:function(_675){ +MochiKit.DOM.setOpacity(this.element,_675); +}}); +MochiKit.Visual.Move=function(_676,_677){ +this.__init__(_676,_677); +}; +MochiKit.Visual.Move.prototype=new MochiKit.Visual.Base(); +MochiKit.Base.update(MochiKit.Visual.Move.prototype,{__init__:function(_678,_679){ +this.element=MochiKit.DOM.getElement(_678); +_679=MochiKit.Base.update({x:0,y:0,mode:"relative"},_679||{}); +this.start(_679); +},setup:function(){ +var d=MochiKit.DOM; +d.makePositioned(this.element); +var s=this.element.style; +var _680=s.visibility; +var _681=s.display; +if(_681=="none"){ +s.visibility="hidden"; +s.display=""; +} +this.originalLeft=parseFloat(d.getStyle(this.element,"left")||"0"); +this.originalTop=parseFloat(d.getStyle(this.element,"top")||"0"); +if(this.options.mode=="absolute"){ +this.options.x-=this.originalLeft; +this.options.y-=this.originalTop; +} +if(_681=="none"){ +s.visibility=_680; +s.display=_681; +} +},update:function(_682){ +MochiKit.DOM.setStyle(this.element,{left:Math.round(this.options.x*_682+this.originalLeft)+"px",top:Math.round(this.options.y*_682+this.originalTop)+"px"}); +}}); +MochiKit.Visual.Scale=function(_683,_684,_685){ +this.__init__(_683,_684,_685); +}; +MochiKit.Visual.Scale.prototype=new MochiKit.Visual.Base(); +MochiKit.Base.update(MochiKit.Visual.Scale.prototype,{__init__:function(_686,_687,_688){ +this.element=MochiKit.DOM.getElement(_686); +_688=MochiKit.Base.update({scaleX:true,scaleY:true,scaleContent:true,scaleFromCenter:false,scaleMode:"box",scaleFrom:100,scaleTo:_687},_688||{}); +this.start(_688); +},setup:function(){ +this.restoreAfterFinish=this.options.restoreAfterFinish||false; +this.elementPositioning=MochiKit.DOM.getStyle(this.element,"position"); +var fe=MochiKit.Iter.forEach; +var b=MochiKit.Base.bind; +this.originalStyle={}; +fe(["top","left","width","height","fontSize"],b(function(k){ +this.originalStyle[k]=this.element.style[k]; +},this)); +this.originalTop=this.element.offsetTop; +this.originalLeft=this.element.offsetLeft; +var _689=MochiKit.DOM.getStyle(this.element,"font-size")||"100%"; +fe(["em","px","%"],b(function(_690){ +if(_689.indexOf(_690)>0){ +this.fontSize=parseFloat(_689); +this.fontSizeType=_690; +} +},this)); +this.factor=(this.options.scaleTo-this.options.scaleFrom)/100; +if(/^content/.test(this.options.scaleMode)){ +this.dims=[this.element.scrollHeight,this.element.scrollWidth]; +}else{ +if(this.options.scaleMode=="box"){ +this.dims=[this.element.offsetHeight,this.element.offsetWidth]; +}else{ +this.dims=[this.options.scaleMode.originalHeight,this.options.scaleMode.originalWidth]; +} +} +},update:function(_691){ +var _692=(this.options.scaleFrom/100)+(this.factor*_691); +if(this.options.scaleContent&&this.fontSize){ +MochiKit.DOM.setStyle(this.element,{fontSize:this.fontSize*_692+this.fontSizeType}); +} +this.setDimensions(this.dims[0]*_692,this.dims[1]*_692); +},finish:function(){ +if(this.restoreAfterFinish){ +MochiKit.DOM.setStyle(this.element,this.originalStyle); +} +},setDimensions:function(_693,_694){ +var d={}; +if(this.options.scaleX){ +d.width=Math.round(_694)+"px"; +} +if(this.options.scaleY){ +d.height=Math.round(_693)+"px"; +} +if(this.options.scaleFromCenter){ +var topd=(_693-this.dims[0])/2; +var _696=(_694-this.dims[1])/2; +if(this.elementPositioning=="absolute"){ +if(this.options.scaleY){ +d.top=this.originalTop-topd+"px"; +} +if(this.options.scaleX){ +d.left=this.originalLeft-_696+"px"; +} +}else{ +if(this.options.scaleY){ +d.top=-topd+"px"; +} +if(this.options.scaleX){ +d.left=-_696+"px"; +} +} +} +MochiKit.DOM.setStyle(this.element,d); +}}); +MochiKit.Visual.Highlight=function(_697,_698){ +this.__init__(_697,_698); +}; +MochiKit.Visual.Highlight.prototype=new MochiKit.Visual.Base(); +MochiKit.Base.update(MochiKit.Visual.Highlight.prototype,{__init__:function(_699,_700){ +this.element=MochiKit.DOM.getElement(_699); +_700=MochiKit.Base.update({startcolor:"#ffff99"},_700||{}); +this.start(_700); +},setup:function(){ +var d=MochiKit.DOM; +var b=MochiKit.Base; +if(d.getStyle(this.element,"display")=="none"){ +this.cancel(); +return; +} +this.oldStyle={backgroundImage:d.getStyle(this.element,"background-image")}; +d.setStyle(this.element,{backgroundImage:"none"}); +if(!this.options.endcolor){ +this.options.endcolor=MochiKit.Color.Color.fromBackground(this.element).toHexString(); +} +if(!this.options.restorecolor){ +this.options.restorecolor=d.getStyle(this.element,"background-color"); +} +this._base=b.map(b.bind(function(i){ +return parseInt(this.options.startcolor.slice(i*2+1,i*2+3),16); +},this),[0,1,2]); +this._delta=b.map(b.bind(function(i){ +return parseInt(this.options.endcolor.slice(i*2+1,i*2+3),16)-this._base[i]; +},this),[0,1,2]); +},update:function(_701){ +var m="#"; +MochiKit.Iter.forEach([0,1,2],MochiKit.Base.bind(function(i){ +m+=MochiKit.Color.toColorPart(Math.round(this._base[i]+this._delta[i]*_701)); +},this)); +MochiKit.DOM.setStyle(this.element,{backgroundColor:m}); +},finish:function(){ +MochiKit.DOM.setStyle(this.element,MochiKit.Base.update(this.oldStyle,{backgroundColor:this.options.endcolor})); +}}); +MochiKit.Visual.ScrollTo=function(_702,_703){ +this.__init__(_702,_703); +}; +MochiKit.Visual.ScrollTo.prototype=new MochiKit.Visual.Base(); +MochiKit.Base.update(MochiKit.Visual.ScrollTo.prototype,{__init__:function(_704,_705){ +this.element=MochiKit.DOM.getElement(_704); +this.start(_705||{}); +},setup:function(){ +var p=MochiKit.Position; +p.prepare(); +var _706=p.cumulativeOffset(this.element); +if(this.options.offset){ +_706.y+=this.options.offset; +} +var max; +if(window.innerHeight){ +max=window.innerHeight-window.height; +}else{ +if(document.documentElement&&document.documentElement.clientHeight){ +max=document.documentElement.clientHeight-document.body.scrollHeight; +}else{ +if(document.body){ +max=document.body.clientHeight-document.body.scrollHeight; +} +} +} +this.scrollStart=p.windowOffset.y; +this.delta=(_706.y>max?max:_706.y)-this.scrollStart; +},update:function(_707){ +var p=MochiKit.Position; +p.prepare(); +window.scrollTo(p.windowOffset.x,this.scrollStart+(_707*this.delta)); +}}); +MochiKit.Visual.fade=function(_708,_709){ +var d=MochiKit.DOM; +var _710=d.getInlineOpacity(_708); +_709=MochiKit.Base.update({from:d.getOpacity(_708)||1,to:0,afterFinishInternal:function(_711){ +if(_711.options.to!==0){ +return; +} +MochiKit.Style.hideElement(_711.element); +d.setStyle(_711.element,{opacity:_710}); +}},_709||{}); +return new MochiKit.Visual.Opacity(_708,_709); +}; +MochiKit.Visual.appear=function(_712,_713){ +var d=MochiKit.DOM; +var v=MochiKit.Visual; +_713=MochiKit.Base.update({from:(d.getStyle(_712,"display")=="none"?0:d.getOpacity(_712)||0),to:1,afterFinishInternal:function(_714){ +v.forceRerendering(_714.element); +},beforeSetupInternal:function(_715){ +d.setOpacity(_715.element,_715.options.from); +MochiKit.Style.showElement(_715.element); +}},_713||{}); +return new v.Opacity(_712,_713); +}; +MochiKit.Visual.puff=function(_716,_717){ +var d=MochiKit.DOM; +var v=MochiKit.Visual; +_716=d.getElement(_716); +var _718={opacity:d.getInlineOpacity(_716),position:d.getStyle(_716,"position")}; +_717=MochiKit.Base.update({beforeSetupInternal:function(_719){ +d.setStyle(_719.effects[0].element,{position:"absolute"}); +},afterFinishInternal:function(_720){ +MochiKit.Style.hideElement(_720.effects[0].element); +d.setStyle(_720.effects[0].element,_718); +}},_717||{}); +return new v.Parallel([new v.Scale(_716,200,{sync:true,scaleFromCenter:true,scaleContent:true,restoreAfterFinish:true}),new v.Opacity(_716,{sync:true,to:0})],_717); +}; +MochiKit.Visual.blindUp=function(_721,_722){ +var d=MochiKit.DOM; +_721=d.getElement(_721); +d.makeClipping(_721); +_722=MochiKit.Base.update({scaleContent:false,scaleX:false,restoreAfterFinish:true,afterFinishInternal:function(_723){ +MochiKit.Style.hideElement(_723.element); +d.undoClipping(_723.element); +}},_722||{}); +return new MochiKit.Visual.Scale(_721,0,_722); +}; +MochiKit.Visual.blindDown=function(_724,_725){ +var d=MochiKit.DOM; +_724=d.getElement(_724); +var _726=MochiKit.Style.getElementDimensions(_724); +_725=MochiKit.Base.update({scaleContent:false,scaleX:false,scaleFrom:0,scaleMode:{originalHeight:_726.h,originalWidth:_726.w},restoreAfterFinish:true,afterSetupInternal:function(_727){ +d.makeClipping(_727.element); +d.setStyle(_727.element,{height:"0px"}); +MochiKit.Style.showElement(_727.element); +},afterFinishInternal:function(_728){ +d.undoClipping(_728.element); +}},_725||{}); +return new MochiKit.Visual.Scale(_724,100,_725); +}; +MochiKit.Visual.switchOff=function(_729,_730){ +var d=MochiKit.DOM; +_729=d.getElement(_729); +var _731=d.getInlineOpacity(_729); +var _730=MochiKit.Base.update({duration:0.3,scaleFromCenter:true,scaleX:false,scaleContent:false,restoreAfterFinish:true,beforeSetupInternal:function(_732){ +d.makePositioned(_732.element); +d.makeClipping(_732.element); +},afterFinishInternal:function(_733){ +MochiKit.Style.hideElement(_733.element); +d.undoClipping(_733.element); +d.undoPositioned(_733.element); +d.setStyle(_733.element,{opacity:_731}); +}},_730||{}); +var v=MochiKit.Visual; +return new v.appear(_729,{duration:0.4,from:0,transition:v.Transitions.flicker,afterFinishInternal:function(_734){ +new v.Scale(_734.element,1,_730); +}}); +}; +MochiKit.Visual.dropOut=function(_735,_736){ +var d=MochiKit.DOM; +_735=d.getElement(_735); +var _737={top:d.getStyle(_735,"top"),left:d.getStyle(_735,"left"),opacity:d.getInlineOpacity(_735)}; +_736=MochiKit.Base.update({duration:0.5,beforeSetupInternal:function(_738){ +d.makePositioned(_738.effects[0].element); +},afterFinishInternal:function(_739){ +MochiKit.Style.hideElement(_739.effects[0].element); +d.undoPositioned(_739.effects[0].element); +d.setStyle(_739.effects[0].element,_737); +}},_736||{}); +var v=MochiKit.Visual; +return new v.Parallel([new v.Move(_735,{x:0,y:100,sync:true}),new v.Opacity(_735,{sync:true,to:0})],_736); +}; +MochiKit.Visual.shake=function(_740,_741){ +var d=MochiKit.DOM; +var v=MochiKit.Visual; +_740=d.getElement(_740); +_741=MochiKit.Base.update({x:-20,y:0,duration:0.05,afterFinishInternal:function(_742){ +d.undoPositioned(_742.element); +d.setStyle(_742.element,oldStyle); +}},_741||{}); +var _743={top:d.getStyle(_740,"top"),left:d.getStyle(_740,"left")}; +return new v.Move(_740,{x:20,y:0,duration:0.05,afterFinishInternal:function(_744){ +new v.Move(_744.element,{x:-40,y:0,duration:0.1,afterFinishInternal:function(_744){ +new v.Move(_744.element,{x:40,y:0,duration:0.1,afterFinishInternal:function(_744){ +new v.Move(_744.element,{x:-40,y:0,duration:0.1,afterFinishInternal:function(_744){ +new v.Move(_744.element,{x:40,y:0,duration:0.1,afterFinishInternal:function(_744){ +new v.Move(_744.element,_741); +}}); +}}); +}}); +}}); +}}); +}; +MochiKit.Visual.slideDown=function(_745,_746){ +var d=MochiKit.DOM; +var b=MochiKit.Base; +_745=d.getElement(_745); +if(!_745.firstChild){ +throw "MochiKit.Visual.slideDown must be used on a element with a child"; +} +d.removeEmptyTextNodes(_745); +var _747=d.getStyle(_745.firstChild,"bottom")||0; +var _748=MochiKit.Style.getElementDimensions(_745); +_746=b.update({scaleContent:false,scaleX:false,scaleFrom:0,scaleMode:{originalHeight:_748.h,originalWidth:_748.w},restoreAfterFinish:true,afterSetupInternal:function(_749){ +d.makePositioned(_749.element); +d.makePositioned(_749.element.firstChild); +if(b.isOpera()){ +d.setStyle(_749.element,{top:""}); +} +d.makeClipping(_749.element); +d.setStyle(_749.element,{height:"0px"}); +MochiKit.Style.showElement(_745); +},afterUpdateInternal:function(_750){ +d.setStyle(_750.element.firstChild,{bottom:(_750.dims[0]-_750.element.clientHeight)+"px"}); +},afterFinishInternal:function(_751){ +d.undoClipping(_751.element); +if(b.isIE()){ +d.undoPositioned(_751.element); +d.undoPositioned(_751.element.firstChild); +}else{ +d.undoPositioned(_751.element.firstChild); +d.undoPositioned(_751.element); +} +d.setStyle(_751.element.firstChild,{bottom:_747}); +}},_746||{}); +return new MochiKit.Visual.Scale(_745,100,_746); +}; +MochiKit.Visual.slideUp=function(_752,_753){ +var d=MochiKit.DOM; +var b=MochiKit.Base; +_752=d.getElement(_752); +if(!_752.firstChild){ +throw "MochiKit.Visual.slideUp must be used on a element with a child"; +} +d.removeEmptyTextNodes(_752); +var _754=d.getStyle(_752.firstChild,"bottom"); +_753=b.update({scaleContent:false,scaleX:false,scaleMode:"box",scaleFrom:100,restoreAfterFinish:true,beforeStartInternal:function(_755){ +d.makePositioned(_755.element); +d.makePositioned(_755.element.firstChild); +if(b.isOpera()){ +d.setStyle(_755.element,{top:""}); +} +d.makeClipping(_755.element); +MochiKit.Style.showElement(_752); +},afterUpdateInternal:function(_756){ +d.setStyle(_756.element.firstChild,{bottom:(_756.dims[0]-_756.element.clientHeight)+"px"}); +},afterFinishInternal:function(_757){ +MochiKit.Style.hideElement(_757.element); +d.undoClipping(_757.element); +d.undoPositioned(_757.element.firstChild); +d.undoPositioned(_757.element); +d.setStyle(_757.element.firstChild,{bottom:_754}); +}},_753||{}); +return new MochiKit.Visual.Scale(_752,0,_753); +}; +MochiKit.Visual.squish=function(_758,_759){ +var d=MochiKit.DOM; +var b=MochiKit.Base; +_759=b.update({restoreAfterFinish:true,beforeSetupInternal:function(_760){ +d.makeClipping(_760.element); +},afterFinishInternal:function(_761){ +MochiKit.Style.hideElement(_761.element); +d.undoClipping(_761.element); +}},_759||{}); +return new MochiKit.Visual.Scale(_758,b.isOpera()?1:0,_759); +}; +MochiKit.Visual.grow=function(_762,_763){ +var d=MochiKit.DOM; +var v=MochiKit.Visual; +_762=d.getElement(_762); +_763=MochiKit.Base.update({direction:"center",moveTransition:v.Transitions.sinoidal,scaleTransition:v.Transitions.sinoidal,opacityTransition:v.Transitions.full},_763||{}); +var _764={top:_762.style.top,left:_762.style.left,height:_762.style.height,width:_762.style.width,opacity:d.getInlineOpacity(_762)}; +var dims=MochiKit.Style.getElementDimensions(_762); +var _766,initialMoveY; +var _767,moveY; +switch(_763.direction){ +case "top-left": +_766=initialMoveY=_767=moveY=0; +break; +case "top-right": +_766=dims.w; +initialMoveY=moveY=0; +_767=-dims.w; +break; +case "bottom-left": +_766=_767=0; +initialMoveY=dims.h; +moveY=-dims.h; +break; +case "bottom-right": +_766=dims.w; +initialMoveY=dims.h; +_767=-dims.w; +moveY=-dims.h; +break; +case "center": +_766=dims.w/2; +initialMoveY=dims.h/2; +_767=-dims.w/2; +moveY=-dims.h/2; +break; +} +var _768=MochiKit.Base.update({beforeSetupInternal:function(_769){ +d.setStyle(_769.effects[0].element,{height:"0px"}); +MochiKit.Style.showElement(_769.effects[0].element); +},afterFinishInternal:function(_770){ +d.undoClipping(_770.effects[0].element); +d.undoPositioned(_770.effects[0].element); +d.setStyle(_770.effects[0].element,_764); +}},_763||{}); +return new v.Move(_762,{x:_766,y:initialMoveY,duration:0.01,beforeSetupInternal:function(_771){ +MochiKit.Style.hideElement(_771.element); +d.makeClipping(_771.element); +d.makePositioned(_771.element); +},afterFinishInternal:function(_772){ +new v.Parallel([new v.Opacity(_772.element,{sync:true,to:1,from:0,transition:_763.opacityTransition}),new v.Move(_772.element,{x:_767,y:moveY,sync:true,transition:_763.moveTransition}),new v.Scale(_772.element,100,{scaleMode:{originalHeight:dims.h,originalWidth:dims.w},sync:true,scaleFrom:MochiKit.Base.isOpera()?1:0,transition:_763.scaleTransition,restoreAfterFinish:true})],_768); +}}); +}; +MochiKit.Visual.shrink=function(_773,_774){ +var d=MochiKit.DOM; +var v=MochiKit.Visual; +_773=d.getElement(_773); +_774=MochiKit.Base.update({direction:"center",moveTransition:v.Transitions.sinoidal,scaleTransition:v.Transitions.sinoidal,opacityTransition:v.Transitions.none},_774||{}); +var _775={top:_773.style.top,left:_773.style.left,height:_773.style.height,width:_773.style.width,opacity:d.getInlineOpacity(_773)}; +var dims=MochiKit.Style.getElementDimensions(_773); +var _776,moveY; +switch(_774.direction){ +case "top-left": +_776=moveY=0; +break; +case "top-right": +_776=dims.w; +moveY=0; +break; +case "bottom-left": +_776=0; +moveY=dims.h; +break; +case "bottom-right": +_776=dims.w; +moveY=dims.h; +break; +case "center": +_776=dims.w/2; +moveY=dims.h/2; +break; +} +var _777=MochiKit.Base.update({beforeStartInternal:function(_778){ +d.makePositioned(_778.effects[0].element); +d.makeClipping(_778.effects[0].element); +},afterFinishInternal:function(_779){ +MochiKit.Style.hideElement(_779.effects[0].element); +d.undoClipping(_779.effects[0].element); +d.undoPositioned(_779.effects[0].element); +d.setStyle(_779.effects[0].element,_775); +}},_774||{}); +return new v.Parallel([new v.Opacity(_773,{sync:true,to:0,from:1,transition:_774.opacityTransition}),new v.Scale(_773,MochiKit.Base.isOpera()?1:0,{sync:true,transition:_774.scaleTransition,restoreAfterFinish:true}),new v.Move(_773,{x:_776,y:moveY,sync:true,transition:_774.moveTransition})],_777); +}; +MochiKit.Visual.pulsate=function(_780,_781){ +var d=MochiKit.DOM; +var v=MochiKit.Visual; +var b=MochiKit.Base; +_780=d.getElement(_780); +var _782=d.getInlineOpacity(_780); +_781=b.update({duration:3,from:0,afterFinishInternal:function(_783){ +d.setStyle(_783.element,{opacity:_782}); +}},_781||{}); +var _784=_781.transition||v.Transitions.sinoidal; +var _785=b.bind(function(pos){ +return _784(1-v.Transitions.pulse(pos)); +},_784); +b.bind(_785,_784); +return new v.Opacity(_780,b.update({transition:_785},_781)); +}; +MochiKit.Visual.fold=function(_786,_787){ +var d=MochiKit.DOM; +var v=MochiKit.Visual; +_786=d.getElement(_786); +var _788={top:_786.style.top,left:_786.style.left,width:_786.style.width,height:_786.style.height}; +d.makeClipping(_786); +_787=MochiKit.Base.update({scaleContent:false,scaleX:false,afterFinishInternal:function(_789){ +new v.Scale(_786,1,{scaleContent:false,scaleY:false,afterFinishInternal:function(_789){ +MochiKit.Style.hideElement(_789.element); +d.undoClipping(_789.element); +d.setStyle(_789.element,_788); +}}); +}},_787||{}); +return new v.Scale(_786,5,_787); +}; +MochiKit.Visual.Color=MochiKit.Color.Color; +MochiKit.Visual.getElementsComputedStyle=MochiKit.DOM.computedStyle; +MochiKit.Visual.__new__=function(){ +var m=MochiKit.Base; +m.nameFunctions(this); +this.EXPORT_TAGS={":common":this.EXPORT,":all":m.concat(this.EXPORT,this.EXPORT_OK)}; +}; +MochiKit.Visual.EXPORT=["roundElement","roundClass","tagifyText","multiple","toggle","Base","Parallel","Opacity","Move","Scale","Highlight","ScrollTo","fade","appear","puff","blindUp","blindDown","switchOff","dropOut","shake","slideDown","slideUp","squish","grow","shrink","pulsate","fold"]; +MochiKit.Visual.EXPORT_OK=["PAIRS"]; +MochiKit.Visual.__new__(); +MochiKit.Base._exportSymbols(this,MochiKit.Visual); +MochiKit.Base.update(MochiKit.Base,{isIE:function(){ +return /MSIE/.test(navigator.userAgent); +},isGecko:function(){ +return /Gecko/.test(navigator.userAgent); +},isKHTML:function(){ +return /Konqueror|Safari|KHTML/.test(navigator.userAgent); +},isSafari:function(){ +return navigator.appVersion.indexOf("AppleWebKit")>0; +},isOpera:function(){ +return navigator.userAgent.indexOf("Opera")>0; +}}); +MochiKit.Base.update(MochiKit.DOM,{getStyle:function(_790,_791){ +_790=MochiKit.DOM.getElement(_790); +var _792=_790.style[MochiKit.Base.camelize(_791)]; +if(!_792){ +if(document.defaultView&&document.defaultView.getComputedStyle){ +var css=document.defaultView.getComputedStyle(_790,null); +_792=css?css.getPropertyValue(_791):null; +}else{ +if(_790.currentStyle){ +_792=_790.currentStyle[MochiKit.Base.camelize(_791)]; +} +} +} +if(MochiKit.Base.isOpera()&&(MochiKit.Base.find(["left","top","right","bottom"],_791))){ +if(MochiKit.DOM.getStyle(_790,"position")=="static"){ +_792="auto"; +} +} +return _792=="auto"?null:_792; +},setStyle:function(_794,_795){ +_794=MochiKit.DOM.getElement(_794); +for(name in _795){ +_794.style[MochiKit.Base.camelize(name)]=_795[name]; +} +},getOpacity:function(_796){ +var _797; +if(_797=MochiKit.DOM.getStyle(_796,"opacity")){ +return parseFloat(_797); +} +if(_797=(MochiKit.DOM.getStyle(_796,"filter")||"").match(/alpha\(opacity=(.*)\)/)){ +if(_797[1]){ +return parseFloat(_797[1])/100; +} +} +return 1; +},getInlineOpacity:function(_798){ +return MochiKit.DOM.getElement(_798).style.opacity||""; +},setOpacity:function(_799,_800){ +_799=MochiKit.DOM.getElement(_799); +if(_800==1){ +MochiKit.DOM.setStyle(_799,{opacity:(MochiKit.Base.isGecko()&&!MochiKit.Base.isKHTML())?0.999999:null}); +if(MochiKit.Base.isIE()){ +MochiKit.DOM.setStyle(_799,{filter:MochiKit.DOM.getStyle(_799,"filter").replace(/alpha\([^\)]*\)/gi,"")}); +} +}else{ +if(_800<0.00001){ +_800=0; +} +MochiKit.DOM.setStyle(_799,{opacity:_800}); +if(MochiKit.Base.isIE()){ +MochiKit.DOM.setStyle(_799,{filter:MochiKit.DOM.getStyle(_799,"filter").replace(/alpha\([^\)]*\)/gi,"")+"alpha(opacity="+_800*100+")"}); +} +} +},isVisible:function(_801){ +return MochiKit.DOM.getElement(_801).style.display!="none"; +},makeClipping:function(_802){ +_802=MochiKit.DOM.getElement(_802); +if(_802._overflow){ +return; +} +_802._overflow=_802.style.overflow; +if((MochiKit.DOM.getStyle(_802,"overflow")||"visible")!="hidden"){ +_802.style.overflow="hidden"; +} +},undoClipping:function(_803){ +_803=MochiKit.DOM.getElement(_803); +if(!_803._overflow){ +return; +} +_803.style.overflow=_803._overflow; +_803._overflow=undefined; +},makePositioned:function(_804){ +_804=MochiKit.DOM.getElement(_804); +var pos=MochiKit.DOM.getStyle(_804,"position"); +if((pos=="static"||!pos)&&!_804._madePositioned){ +_804._madePositioned=true; +_804.style.position="relative"; +if(MochiKit.Base.isOpera()){ +_804.style.top=0; +_804.style.left=0; +} +} +},undoPositioned:function(_805){ +_805=MochiKit.DOM.getElement(_805); +if(_805._madePositioned){ +_805._madePositioned=undefined; +_805.style.position=_805.style.top=_805.style.left=_805.style.bottom=_805.style.right=""; +} +},getFirstElementByTagAndClassName:function(_806,_807,_808){ +var self=MochiKit.DOM; +if(typeof (_806)=="undefined"||_806===null){ +_806="*"; +} +if(typeof (_808)=="undefined"||_808===null){ +_808=self._document; +} +_808=self.getElement(_808); +var _809=(_808.getElementsByTagName(_806)||self._document.all); +if(typeof (_807)=="undefined"||_807===null){ +return MochiKit.Base.extend(null,_809); +} +for(var i=0;i<_809.length;i++){ +var _810=_809[i]; +var _811=_810.className.split(" "); +for(var j=0;j<_811.length;j++){ +if(_811[j]==_807){ +return _810; +} +} +} +},isParent:function(_812,_813){ +if(!_812.parentNode||_812==_813){ +return false; +} +if(_812.parentNode==_813){ +return true; +} +return MochiKit.DOM.isParent(_812.parentNode,_813); +}}); +MochiKit.Position={includeScrollOffsets:false,prepare:function(){ +var _814=window.pageXOffset||document.documentElement.scrollLeft||document.body.scrollLeft||0; +var _815=window.pageYOffset||document.documentElement.scrollTop||document.body.scrollTop||0; +this.windowOffset=new MochiKit.Style.Coordinates(_814,_815); +},cumulativeOffset:function(_816){ +var _817=0; +var _818=0; +do{ +_817+=_816.offsetTop||0; +_818+=_816.offsetLeft||0; +_816=_816.offsetParent; +}while(_816); +return new MochiKit.Style.Coordinates(_818,_817); +},realOffset:function(_819){ +var _820=0; +var _821=0; +do{ +_820+=_819.scrollTop||0; +_821+=_819.scrollLeft||0; +_819=_819.parentNode; +}while(_819); +return new MochiKit.Style.Coordinates(_821,_820); +},within:function(_822,x,y){ +if(this.includeScrollOffsets){ +return this.withinIncludingScrolloffsets(_822,x,y); +} +this.xcomp=x; +this.ycomp=y; +this.offset=this.cumulativeOffset(_822); +if(_822.style.position=="fixed"){ +this.offset.x+=this.windowOffset.x; +this.offset.y+=this.windowOffset.y; +} +return (y>=this.offset.y&&y=this.offset.x&&x=this.offset.y&&this.ycomp=this.offset.x&&this.xcomp0){ +drop=this.findDeepestChild(_851); +MochiKit.Position.within(drop.element,_849.page.x,_849.page.y); +drop.options.onhover(_850,drop.element,MochiKit.Position.overlap(drop.options.overlap,drop.element)); +drop.activate(); +} +},fire:function(_852,_853){ +if(!this.last_active){ +return; +} +MochiKit.Position.prepare(); +if(this.last_active.isAffected(_852.mouse(),_853)){ +this.last_active.options.ondrop(_853,this.last_active.element,_852); +} +},reset:function(_854){ +MochiKit.Base.map(function(drop){ +if(drop.options.activeclass){ +MochiKit.DOM.removeElementClass(drop.element,drop.options.activeclass); +} +drop.options.ondesactive(drop.element,_854); +},this.drops); +if(this.last_active){ +this.last_active.deactivate(); +} +}}; +MochiKit.DragAndDrop.Droppable=function(_855,_856){ +this.__init__(_855,_856); +}; +MochiKit.DragAndDrop.Droppable.prototype={__class__:MochiKit.DragAndDrop.Droppable,__init__:function(_857,_858){ +var d=MochiKit.DOM; +var b=MochiKit.Base; +this.element=d.getElement(_857); +this.options=b.update({greedy:true,hoverclass:null,activeclass:null,hoverfunc:b.noop,accept:null,onactive:b.noop,ondesactive:b.noop,onhover:b.noop,ondrop:b.noop,containment:[],tree:false},_858||{}); +this.options._containers=[]; +b.map(MochiKit.Base.bind(function(c){ +this.options._containers.push(d.getElement(c)); +},this),this.options.containment); +d.makePositioned(this.element); +MochiKit.DragAndDrop.Droppables.register(this); +},isContained:function(_859){ +if(this._containers){ +var _860; +if(this.options.tree){ +_860=_859.treeNode; +}else{ +_860=_859.parentNode; +} +return MochiKit.Iter.some(this._containers,function(c){ +return _860==c; +}); +}else{ +return true; +} +},isAccepted:function(_861){ +return ((!this.options.accept)||MochiKit.Iter.some(this.options.accept,function(c){ +return MochiKit.DOM.hasElementClass(_861,c); +})); +},isAffected:function(_862,_863){ +return ((this.element!=_863)&&this.isContained(_863)&&this.isAccepted(_863)&&MochiKit.Position.within(this.element,_862.page.x,_862.page.y)); +},deactivate:function(){ +if(this.options.hoverclass){ +MochiKit.DOM.removeElementClass(this.element,this.options.hoverclass); +} +this.options.hoverfunc(this.element,false); +MochiKit.DragAndDrop.Droppables.last_active=null; +},activate:function(){ +if(this.options.hoverclass){ +MochiKit.DOM.addElementClass(this.element,this.options.hoverclass); +} +this.options.hoverfunc(this.element,true); +MochiKit.DragAndDrop.Droppables.last_active=this; +},destroy:function(){ +MochiKit.DragAndDrop.Droppables.unregister(this); +},repr:function(){ +return "["+this.__class__.NAME+", options:"+MochiKit.Base.repr(this.options)+"]"; +}}; +MochiKit.DragAndDrop.Draggables={drags:[],observers:[],register:function(_864){ +if(this.drags.length===0){ +var conn=MochiKit.Signal.connect; +this.eventMouseUp=conn(document,"onmouseup",this,this.endDrag); +this.eventMouseMove=conn(document,"onmousemove",this,this.updateDrag); +this.eventKeypress=conn(document,"onkeypress",this,this.keyPress); +} +this.drags.push(_864); +},unregister:function(_866){ +this.drags=MochiKit.Base.filter(function(d){ +return d!=_866; +},this.drags); +if(this.drags.length===0){ +var disc=MochiKit.Signal.disconnect; +disc(this.eventMouseUp); +disc(this.eventMouseMove); +disc(this.eventKeypress); +} +},activate:function(_868){ +window.focus(); +this.activeDraggable=_868; +},deactivate:function(){ +this.activeDraggable=null; +},updateDrag:function(_869){ +if(!this.activeDraggable){ +return; +} +var _870=_869.mouse(); +if(this._lastPointer&&(MochiKit.Base.repr(this._lastPointer.page)==MochiKit.Base.repr(_870.page))){ +return; +} +this._lastPointer=_870; +this.activeDraggable.updateDrag(_869,_870); +},endDrag:function(_871){ +if(!this.activeDraggable){ +return; +} +this._lastPointer=null; +this.activeDraggable.endDrag(_871); +this.activeDraggable=null; +},keyPress:function(_872){ +if(this.activeDraggable){ +this.activeDraggable.keyPress(_872); +} +},addObserver:function(_873){ +this.observers.push(_873); +this._cacheObserverCallbacks(); +},removeObserver:function(_874){ +this.observers=MochiKit.Base.filter(function(o){ +return o.element!=_874; +},this.observers); +this._cacheObserverCallbacks(); +},notify:function(_875,_876,_877){ +if(this[_875+"Count"]>0){ +MochiKit.Base.map(function(o){ +if(o[_875]){ +o[_875](_875,_876,_877); +} +},this.observers); +} +},_cacheObserverCallbacks:function(){ +var b=MochiKit.Base; +var self=MochiKit.DragAndDrop.Draggables; +b.map(function(_878){ +self[_878+"Count"]=b.filter(function(o){ +return o[_878]; +},self.observers).length; +},["onStart","onEnd","onDrag"]); +}}; +MochiKit.DragAndDrop.Draggable=function(_879,_880){ +this.__init__(_879,_880); +}; +MochiKit.DragAndDrop.Draggable.prototype={__class__:MochiKit.DragAndDrop.Draggable,__init__:function(_881,_882){ +var v=MochiKit.Visual; +var b=MochiKit.Base; +_882=b.update({handle:false,starteffect:function(_883){ +this._savedOpacity=MochiKit.DOM.getOpacity(_883)||1; +new v.Opacity(_883,{duration:0.2,from:this._savedOpacity,to:0.7}); +},reverteffect:function(_884,_885,_886){ +var dur=Math.sqrt(Math.abs(_885^2)+Math.abs(_886^2))*0.02; +return new v.Move(_884,{x:-_886,y:-_885,duration:dur}); +},endeffect:function(_888){ +new v.Opacity(_888,{duration:0.2,from:0.7,to:this._savedOpacity}); +},onchange:b.noop,zindex:1000,revert:false,scroll:false,scrollSensitivity:20,scrollSpeed:15,snap:false},_882||{}); +var d=MochiKit.DOM; +this.element=d.getElement(_881); +if(_882.handle&&(typeof (_882.handle)=="string")){ +this.handle=d.getFirstElementByTagAndClassName(null,_882.handle,this.element); +} +if(!this.handle){ +this.handle=d.getElement(_882.handle); +} +if(!this.handle){ +this.handle=this.element; +} +if(_882.scroll&&!_882.scroll.scrollTo&&!_882.scroll.outerHTML){ +_882.scroll=d.getElement(_882.scroll); +} +d.makePositioned(this.element); +this.delta=this.currentDelta(); +this.options=_882; +this.dragging=false; +this.eventMouseDown=MochiKit.Signal.connect(this.handle,"onmousedown",this,this.initDrag); +MochiKit.DragAndDrop.Draggables.register(this); +},destroy:function(){ +MochiKit.Signal.disconnect(this.eventMouseDown); +MochiKit.DragAndDrop.Draggables.unregister(this); +},currentDelta:function(){ +var s=MochiKit.DOM.getStyle; +return [parseInt(s(this.element,"left")||"0"),parseInt(s(this.element,"top")||"0")]; +},initDrag:function(_889){ +if(!_889.mouse().button.left){ +return; +} +var src=_889.target; +if(src.tagName&&(src.tagName=="INPUT"||src.tagName=="SELECT"||src.tagName=="OPTION"||src.tagName=="BUTTON"||src.tagName=="TEXTAREA")){ +return; +} +if(this._revert){ +this._revert.cancel(); +this._revert=null; +} +var _890=_889.mouse(); +var pos=MochiKit.Position.cumulativeOffset(this.element); +this.offset=[_890.page.x-pos.x,_890.page.y-pos.y]; +MochiKit.DragAndDrop.Draggables.activate(this); +_889.stop(); +},startDrag:function(_891){ +this.dragging=true; +if(this.options.selectclass){ +MochiKit.DOM.addElementClass(this.element,this.options.selectclass); +} +if(this.options.zindex){ +this.originalZ=parseInt(MochiKit.DOM.getStyle(this.element,"z-index")||"0"); +this.element.style.zIndex=this.options.zindex; +} +if(this.options.ghosting){ +this._clone=this.element.cloneNode(true); +this.ghostPosition=MochiKit.Position.absolutize(this.element); +this.element.parentNode.insertBefore(this._clone,this.element); +} +if(this.options.scroll){ +if(this.options.scroll==window){ +var _892=this._getWindowScroll(this.options.scroll); +this.originalScrollLeft=_892.left; +this.originalScrollTop=_892.top; +}else{ +this.originalScrollLeft=this.options.scroll.scrollLeft; +this.originalScrollTop=this.options.scroll.scrollTop; +} +} +MochiKit.DragAndDrop.Droppables.prepare(this.element); +MochiKit.DragAndDrop.Draggables.notify("onStart",this,_891); +if(this.options.starteffect){ +this.options.starteffect(this.element); +} +},updateDrag:function(_893,_894){ +if(!this.dragging){ +this.startDrag(_893); +} +MochiKit.Position.prepare(); +MochiKit.DragAndDrop.Droppables.show(_894,this.element); +MochiKit.DragAndDrop.Draggables.notify("onDrag",this,_893); +this.draw(_894); +this.options.onchange(this); +if(this.options.scroll){ +this.stopScrolling(); +var p,q; +if(this.options.scroll==window){ +var s=this._getWindowScroll(this.options.scroll); +p=new MochiKit.Style.Coordinates(s.left,s.top); +q=new MochiKit.Style.Coordinates(s.left+s.width,s.top+s.height); +}else{ +p=MochiKit.Position.page(this.options.scroll); +p.x+=this.options.scroll.scrollLeft; +p.y+=this.options.scroll.scrollTop; +q=new MochiKit.Style.Coordinates(p.x+this.options.scroll.offsetWidth,p.y+this.options.scroll.offsetHeight); +} +var _895=[0,0]; +if(_894.page.x>(q.x-this.options.scrollSensitivity)){ +_895[0]=_894.page.x-(q.x-this.options.scrollSensitivity); +}else{ +if(_894.page.x<(p.x+this.options.scrollSensitivity)){ +_895[0]=_894.page.x-(p.x+this.options.scrollSensitivity); +} +} +if(_894.page.y>(q.y-this.options.scrollSensitivity)){ +_895[1]=_894.page.y-(q.y-this.options.scrollSensitivity); +}else{ +if(_894.page.y<(p.y+this.options.scrollSensitivity)){ +_895[1]=_894.page.y-(p.y+this.options.scrollSensitivity); +} +} +this.startScrolling(_895); +} +if(MochiKit.Base.isSafari()){ +window.scrollBy(0,0); +} +_893.stop(); +},finishDrag:function(_896,_897){ +var dr=MochiKit.DragAndDrop; +this.dragging=false; +if(this.options.selectclass){ +MochiKit.DOM.removeElementClass(this.element,this.options.selectclass); +} +if(this.options.ghosting){ +MochiKit.Position.relativize(this.element,this.ghostPosition); +MochiKit.DOM.removeElement(this._clone); +this._clone=null; +} +if(_897){ +dr.Droppables.fire(_896,this.element); +} +dr.Draggables.notify("onEnd",this,_896); +var _899=this.options.revert; +if(_899&&typeof (_899)=="function"){ +_899=_899(this.element); +} +var d=this.currentDelta(); +if(_899&&this.options.reverteffect){ +this._revert=this.options.reverteffect(this.element,d[1]-this.delta[1],d[0]-this.delta[0]); +}else{ +this.delta=d; +} +if(this.options.zindex){ +this.element.style.zIndex=this.originalZ; +} +if(this.options.endeffect){ +this.options.endeffect(this.element); +} +dr.Draggables.deactivate(); +dr.Droppables.reset(this.element); +},keyPress:function(_900){ +if(_900.keyString!="KEY_ESCAPE"){ +return; +} +this.finishDrag(_900,false); +_900.stop(); +},endDrag:function(_901){ +if(!this.dragging){ +return; +} +this.stopScrolling(); +this.finishDrag(_901,true); +_901.stop(); +},draw:function(_902){ +var pos=MochiKit.Position.cumulativeOffset(this.element); +var d=this.currentDelta(); +pos.x-=d[0]; +pos.y-=d[1]; +if(this.options.scroll&&!this.options.scroll.scrollTo){ +pos.x-=this.options.scroll.scrollLeft-this.originalScrollLeft; +pos.y-=this.options.scroll.scrollTop-this.originalScrollTop; +} +var p=[_902.page.x-pos.x-this.offset[0],_902.page.y-pos.y-this.offset[1]]; +if(this.options.snap){ +if(typeof (this.options.snap)=="function"){ +p=this.options.snap(p[0],p[1]); +}else{ +if(this.options.snap instanceof Array){ +var i=-1; +p=MochiKit.Base.map(MochiKit.Base.bind(function(v){ +i+=1; +return Math.round(v/this.options.snap[i])*this.options.snap[i]; +},this),p); +}else{ +p=MochiKit.Base.map(MochiKit.Base.bind(function(v){ +return Math.round(v/this.options.snap)*this.options.snap; +},this),p); +} +} +} +var _903=this.element.style; +if((!this.options.constraint)||(this.options.constraint=="horizontal")){ +_903.left=p[0]+"px"; +} +if((!this.options.constraint)||(this.options.constraint=="vertical")){ +_903.top=p[1]+"px"; +} +if(_903.visibility=="hidden"){ +_903.visibility=""; +} +},stopScrolling:function(){ +if(this.scrollInterval){ +clearInterval(this.scrollInterval); +this.scrollInterval=null; +} +},startScrolling:function(_904){ +if(!_904[0]||!_904[1]){ +return; +} +this.scrollSpeed=[_904[0]*this.options.scrollSpeed,_904[1]*this.options.scrollSpeed]; +this.lastScrolled=new Date(); +this.scrollInterval=setInterval(MochiKit.Base.bind(this.scroll,this),10); +},scroll:function(){ +var _905=new Date(); +var _906=_905-this.lastScrolled; +this.lastScrolled=_905; +if(this.options.scroll==window){ +var s=this._getWindowScroll(this.options.scroll); +if(this.scrollSpeed[0]||this.scrollSpeed[1]){ +var d=_906/1000; +this.options.scroll.scrollTo(s.left+d*this.scrollSpeed[0],s.top+d*this.scrollSpeed[1]); +} +}else{ +this.options.scroll.scrollLeft+=this.scrollSpeed[0]*_906/1000; +this.options.scroll.scrollTop+=this.scrollSpeed[1]*_906/1000; +} +var d=MochiKit.DragAndDrop; +MochiKit.Position.prepare(); +d.Droppables.show(d.Draggables._lastPointer,this.element); +this.draw(d.Draggables._lastPointer); +this.options.onchange(this); +},_getWindowScroll:function(w){ +var T,L,W,H; +with(w.document){ +if(w.document.documentElement&&documentElement.scrollTop){ +T=documentElement.scrollTop; +L=documentElement.scrollLeft; +}else{ +if(w.document.body){ +T=body.scrollTop; +L=body.scrollLeft; +} +} +if(w.innerWidth){ +W=w.innerWidth; +H=w.innerHeight; +}else{ +if(w.document.documentElement&&documentElement.clientWidth){ +W=documentElement.clientWidth; +H=documentElement.clientHeight; +}else{ +W=body.offsetWidth; +H=body.offsetHeight; +} +} +} +return {top:T,left:L,width:W,height:H}; +},repr:function(){ +return "["+this.__class__.NAME+", options:"+MochiKit.Base.repr(this.options)+"]"; +}}; +MochiKit.DragAndDrop.__new__=function(){ +MochiKit.Base.nameFunctions(this); +this.EXPORT_TAGS={":common":this.EXPORT,":all":MochiKit.Base.concat(this.EXPORT,this.EXPORT_OK)}; +}; +MochiKit.DragAndDrop.__new__(); +MochiKit.Base._exportSymbols(this,MochiKit.DragAndDrop); +if(typeof (dojo)!="undefined"){ +dojo.provide("MochiKit.DragAndDrop"); +dojo.require("MochiKit.Base"); +dojo.require("MochiKit.DOM"); +dojo.require("MochiKit.Iter"); +} +if(typeof (JSAN)!="undefined"){ +JSAN.use("MochiKit.Base",[]); +JSAN.use("MochiKit.DOM",[]); +JSAN.use("MochiKit.Iter",[]); +} +try{ +if(typeof (MochiKit.Base)=="undefined"||typeof (MochiKit.DOM)=="undefined"||typeof (MochiKit.Iter)=="undefined"){ +throw ""; +} +} +catch(e){ +throw "MochiKit.DragAndDrop depends on MochiKit.Base, MochiKit.DOM and MochiKit.Iter!"; +} +if(typeof (MochiKit.Sortable)=="undefined"){ +MochiKit.Sortable={}; +} +MochiKit.Sortable.NAME="MochiKit.Sortable"; +MochiKit.Sortable.VERSION="1.4"; +MochiKit.Sortable.__repr__=function(){ +return "["+this.NAME+" "+this.VERSION+"]"; +}; +MochiKit.Sortable.toString=function(){ +return this.__repr__(); +}; +MochiKit.Sortable.EXPORT=["SortableObserver"]; +MochiKit.DragAndDrop.EXPORT_OK=["Sortable"]; +MochiKit.Sortable.SortableObserver=function(_908,_909){ +this.__init__(_908,_909); +}; +MochiKit.Sortable.SortableObserver.prototype={__init__:function(_910,_911){ +this.element=MochiKit.DOM.getElement(_910); +this.observer=_911; +this.lastValue=MochiKit.Sortable.Sortable.serialize(this.element); +},onStart:function(){ +this.lastValue=MochiKit.Sortable.Sortable.serialize(this.element); +},onEnd:function(){ +MochiKit.Sortable.Sortable.unmark(); +if(this.lastValue!=MochiKit.Sortable.Sortable.serialize(this.element)){ +this.observer(this.element); +} +}}; +MochiKit.Sortable.Sortable={sortables:{},_findRootElement:function(_912){ +while(_912.tagName!="BODY"){ +if(_912.id&&MochiKit.Sortable.Sortable.sortables[_912.id]){ +return _912; +} +_912=_912.parentNode; +} +},options:function(_913){ +_913=MochiKit.Sortable.Sortable._findRootElement(MochiKit.DOM.getElement(_913)); +if(!_913){ +return; +} +return MochiKit.Sortable.Sortable.sortables[_913.id]; +},destroy:function(_914){ +var s=MochiKit.Sortable.Sortable.options(_914); +var b=MochiKit.Base; +var d=MochiKit.DragAndDrop; +if(s){ +d.Draggables.removeObserver(s.element); +b.map(function(dr){ +d.Droppables.remove(dr); +},s.droppables); +b.map(function(dr){ +dr.destroy(); +},s.draggables); +delete MochiKit.Sortable.Sortable.sortables[s.element.id]; +} +},create:function(_915,_916){ +_915=MochiKit.DOM.getElement(_915); +var self=MochiKit.Sortable.Sortable; +_916=MochiKit.Base.update({element:_915,tag:"li",dropOnEmpty:false,tree:false,treeTag:"ul",overlap:"vertical",constraint:"vertical",containment:[_915],handle:false,only:false,hoverclass:null,ghosting:false,scroll:false,scrollSensitivity:20,scrollSpeed:15,format:/^[^_]*_(.*)$/,onChange:MochiKit.Base.noop,onUpdate:MochiKit.Base.noop,accept:null},_916); +self.destroy(_915); +var _917={revert:true,ghosting:_916.ghosting,scroll:_916.scroll,scrollSensitivity:_916.scrollSensitivity,scrollSpeed:_916.scrollSpeed,constraint:_916.constraint,handle:_916.handle}; +if(_916.starteffect){ +_917.starteffect=_916.starteffect; +} +if(_916.reverteffect){ +_917.reverteffect=_916.reverteffect; +}else{ +if(_916.ghosting){ +_917.reverteffect=function(_918){ +_918.style.top=0; +_918.style.left=0; +}; +} +} +if(_916.endeffect){ +_917.endeffect=_916.endeffect; +} +if(_916.zindex){ +_917.zindex=_916.zindex; +} +var _919={overlap:_916.overlap,containment:_916.containment,hoverclass:_916.hoverclass,onhover:self.onHover,tree:_916.tree,accept:_916.accept}; +var _920={onhover:self.onEmptyHover,overlap:_916.overlap,containment:_916.containment,hoverclass:_916.hoverclass,accept:_916.accept}; +MochiKit.DOM.removeEmptyTextNodes(_915); +_916.draggables=[]; +_916.droppables=[]; +if(_916.dropOnEmpty||_916.tree){ +new MochiKit.DragAndDrop.Droppable(_915,_920); +_916.droppables.push(_915); +} +MochiKit.Base.map(function(e){ +var _921=_916.handle?MochiKit.DOM.getFirstElementByTagAndClassName(null,_916.handle,e):e; +_916.draggables.push(new MochiKit.DragAndDrop.Draggable(e,MochiKit.Base.update(_917,{handle:_921}))); +new MochiKit.DragAndDrop.Droppable(e,_919); +if(_916.tree){ +e.treeNode=_915; +} +_916.droppables.push(e); +},(self.findElements(_915,_916)||[])); +if(_916.tree){ +MochiKit.Base.map(function(e){ +new MochiKit.DragAndDrop.Droppable(e,_920); +e.treeNode=_915; +_916.droppables.push(e); +},(self.findTreeElements(_915,_916)||[])); +} +self.sortables[_915.id]=_916; +MochiKit.DragAndDrop.Draggables.addObserver(new MochiKit.Sortable.SortableObserver(_915,_916.onUpdate)); +},findElements:function(_922,_923){ +return MochiKit.Sortable.Sortable.findChildren(_922,_923.only,_923.tree?true:false,_923.tag); +},findTreeElements:function(_924,_925){ +return MochiKit.Sortable.Sortable.findChildren(_924,_925.only,_925.tree?true:false,_925.treeTag); +},findChildren:function(_926,only,_928,_929){ +if(!_926.hasChildNodes()){ +return null; +} +_929=_929.toUpperCase(); +if(only){ +only=MochiKit.Base.flattenArray([only]); +} +var _930=[]; +MochiKit.Base.map(function(e){ +if(e.tagName&&e.tagName.toUpperCase()==_929&&(!only||MochiKit.Iter.some(only,function(c){ +return MochiKit.DOM.hasElementClass(e,c); +}))){ +_930.push(e); +} +if(_928){ +var _931=MochiKit.Sortable.Sortable.findChildren(e,only,_928,_929); +if(_931&&_931.length>0){ +_930=_930.concat(_931); +} +} +},_926.childNodes); +return _930; +},onHover:function(_932,_933,_934){ +if(MochiKit.DOM.isParent(_933,_932)){ +return; +} +var self=MochiKit.Sortable.Sortable; +if(_934>0.33&&_934<0.66&&self.options(_933).tree){ +return; +}else{ +if(_934>0.5){ +self.mark(_933,"before"); +if(_933.previousSibling!=_932){ +var _935=_932.parentNode; +_932.style.visibility="hidden"; +_933.parentNode.insertBefore(_932,_933); +if(_933.parentNode!=_935){ +self.options(_935).onChange(_932); +} +self.options(_933.parentNode).onChange(_932); +} +}else{ +self.mark(_933,"after"); +var _936=_933.nextSibling||null; +if(_936!=_932){ +var _935=_932.parentNode; +_932.style.visibility="hidden"; +_933.parentNode.insertBefore(_932,_936); +if(_933.parentNode!=_935){ +self.options(_935).onChange(_932); +} +self.options(_933.parentNode).onChange(_932); +} +} +} +},_offsetSize:function(_937,type){ +if(type=="vertical"||type=="height"){ +return _937.offsetHeight; +}else{ +return _937.offsetWidth; +} +},onEmptyHover:function(_939,_940,_941){ +var _942=_939.parentNode; +var self=MochiKit.Sortable.Sortable; +var _943=self.options(_940); +if(!MochiKit.DOM.isParent(_940,_939)){ +var _944; +var _945=self.findElements(_940,{tag:_943.tag,only:_943.only}); +var _946=null; +if(_945){ +var _947=self._offsetSize(_940,_943.overlap)*(1-_941); +for(_944=0;_944<_945.length;_944+=1){ +if(_947-self._offsetSize(_945[_944],_943.overlap)>=0){ +_947-=self._offsetSize(_945[_944],_943.overlap); +}else{ +if(_947-(self._offsetSize(_945[_944],_943.overlap)/2)>=0){ +_946=_944+1<_945.length?_945[_944+1]:null; +break; +}else{ +_946=_945[_944]; +break; +} +} +} +} +_940.insertBefore(_939,_946); +self.options(_942).onChange(_939); +_943.onChange(_939); +} +},unmark:function(){ +var m=MochiKit.Sortable.Sortable._marker; +if(m){ +MochiKit.Style.hideElement(m); +} +},mark:function(_948,_949){ +var d=MochiKit.DOM; +var self=MochiKit.Sortable.Sortable; +var _950=self.options(_948.parentNode); +if(_950&&!_950.ghosting){ +return; +} +if(!self._marker){ +self._marker=d.getElement("dropmarker")||document.createElement("DIV"); +MochiKit.Style.hideElement(self._marker); +d.addElementClass(self._marker,"dropmarker"); +self._marker.style.position="absolute"; +document.getElementsByTagName("body").item(0).appendChild(self._marker); +} +var _951=MochiKit.Position.cumulativeOffset(_948); +self._marker.style.left=_951.x+"px"; +self._marker.style.top=_951.y+"px"; +if(_949=="after"){ +if(_950.overlap=="horizontal"){ +self._marker.style.left=(_951.x+_948.clientWidth)+"px"; +}else{ +self._marker.style.top=(_951.y+_948.clientHeight)+"px"; +} +} +MochiKit.Style.showElement(self._marker); +},_tree:function(_952,_953,_954){ +var self=MochiKit.Sortable.Sortable; +var _955=self.findElements(_952,_953)||[]; +for(var i=0;i<_955.length;++i){ +var _956=_955[i].id.match(_953.format); +if(!_956){ +continue; +} +var _957={id:encodeURIComponent(_956?_956[1]:null),element:_952,parent:_954,children:[],position:_954.children.length,container:self._findChildrenElement(_955[i],_953.treeTag.toUpperCase())}; +if(_957.container){ +self._tree(_957.container,_953,_957); +} +_954.children.push(_957); +} +return _954; +},_findChildrenElement:function(_958,_959){ +if(_958&&_958.hasChildNodes){ +for(var i=0;i<_958.childNodes.length;++i){ +if(_958.childNodes[i].tagName==_959){ +return _958.childNodes[i]; +} +} +} +return null; +},tree:function(_960,_961){ +_960=MochiKit.DOM.getElement(_960); +var _962=MochiKit.Sortable.Sortable.options(_960); +_961=MochiKit.Base.update({tag:_962.tag,treeTag:_962.treeTag,only:_962.only,name:_960.id,format:_962.format},_961||{}); +var root={id:null,parent:null,children:new Array,container:_960,position:0}; +return MochiKit.Sortable.Sortable._tree(_960,_961,root); +},setSequence:function(_964,_965,_966){ +var self=MochiKit.Sortable.Sortable; +var b=MochiKit.Base; +_964=MochiKit.DOM.getElement(_964); +_966=b.update(self.options(_964),_966||{}); +var _967={}; +b.map(function(n){ +var m=n.id.match(_966.format); +if(m){ +_967[m[1]]=[n,n.parentNode]; +} +n.parentNode.removeChild(n); +},self.findElements(_964,_966)); +b.map(function(_968){ +var n=_967[_968]; +if(n){ +n[1].appendChild(n[0]); +delete _967[_968]; +} +},_965); +},_constructIndex:function(node){ +var _969=""; +do{ +if(node.id){ +_969="["+node.position+"]"+_969; +} +}while((node=node.parent)!=null); +return _969; +},sequence:function(_970,_971){ +_970=MochiKit.DOM.getElement(_970); +var self=MochiKit.Sortable.Sortable; +var _971=MochiKit.Base.update(self.options(_970),_971||{}); +return MochiKit.Base.map(function(item){ +return item.id.match(_971.format)?item.id.match(_971.format)[1]:""; +},MochiKit.DOM.getElement(self.findElements(_970,_971)||[])); +},serialize:function(_973,_974){ +_973=MochiKit.DOM.getElement(_973); +var self=MochiKit.Sortable.Sortable; +_974=MochiKit.Base.update(self.options(_973),_974||{}); +var name=encodeURIComponent(_974.name||_973.id); +if(_974.tree){ +return MochiKit.Base.flattenArray(MochiKit.Base.map(function(item){ +return [name+self._constructIndex(item)+"[id]="+encodeURIComponent(item.id)].concat(item.children.map(arguments.callee)); +},self.tree(_973,_974).children)).join("&"); +}else{ +return MochiKit.Base.map(function(item){ +return name+"[]="+encodeURIComponent(item); +},self.sequence(_973,_974)).join("&"); +} +}}; +if(typeof (MochiKit)=="undefined"){ +MochiKit={}; +} +if(typeof (MochiKit.MochiKit)=="undefined"){ +MochiKit.MochiKit={}; +} +MochiKit.MochiKit.NAME="MochiKit.MochiKit"; +MochiKit.MochiKit.VERSION="1.4"; +MochiKit.MochiKit.__repr__=function(){ +return "["+this.NAME+" "+this.VERSION+"]"; +}; +MochiKit.MochiKit.toString=function(){ +return this.__repr__(); +}; +MochiKit.MochiKit.SUBMODULES=["Base","Iter","Logging","DateTime","Format","Async","DOM","Style","LoggingPane","Color","Signal","Visual","New","DragAndDrop","Sortable"]; +if(typeof (JSAN)!="undefined"||typeof (dojo)!="undefined"){ +if(typeof (dojo)!="undefined"){ +dojo.provide("MochiKit.MochiKit"); +dojo.require("MochiKit.*"); +} +if(typeof (JSAN)!="undefined"){ +(function(lst){ +for(var i=0;i"); +} +} +})(); +} + + From cfbolz at codespeak.net Mon Dec 4 12:03:42 2006 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Mon, 4 Dec 2006 12:03:42 +0100 (CET) Subject: [pypy-svn] r35247 - pypy/dist/pypy/lang/prolog/interpreter Message-ID: <20061204110342.B0CEE1006C@code0.codespeak.net> Author: cfbolz Date: Mon Dec 4 12:03:40 2006 New Revision: 35247 Modified: pypy/dist/pypy/lang/prolog/interpreter/parsing.py Log: small changes to keep up with the new things in the parser Modified: pypy/dist/pypy/lang/prolog/interpreter/parsing.py ============================================================================== --- pypy/dist/pypy/lang/prolog/interpreter/parsing.py (original) +++ pypy/dist/pypy/lang/prolog/interpreter/parsing.py Mon Dec 4 12:03:40 2006 @@ -225,21 +225,24 @@ def transform(self, node): if isinstance(node, Symbol): return node + children = [c for c in node.children + if isinstance(c, Symbol) or ( + isinstance(c, Nonterminal) and len(c.children))] if isinstance(node, Nonterminal): - if len(node.children) == 1: + if len(children) == 1: return Nonterminal( - node.symbol, [self.transform(node.children[0])]) - if len(node.children) == 2 or len(node.children) == 3: - left = node.children[-2] - right = node.children[-1] + node.symbol, [self.transform(children[0])]) + if len(children) == 2 or len(children) == 3: + left = children[-2] + right = children[-1] if (isinstance(right, Nonterminal) and right.symbol.startswith("extraexpr")): - if len(node.children) == 2: + if len(children) == 2: leftreplacement = self.transform(left) else: leftreplacement = Nonterminal( node.symbol, - [self.transform(node.children[0]), + [self.transform(children[0]), self.transform(left)]) children = [leftreplacement, self.transform(right.children[0]), @@ -247,14 +250,17 @@ newnode = Nonterminal(node.symbol, children) return self.transform_extra(right, newnode) - children = [self.transform(child) for child in node.children] + children = [self.transform(child) for child in children] return Nonterminal(node.symbol, children) def transform_extra(self, extranode, child): + children = [c for c in extranode.children + if isinstance(c, Symbol) or ( + isinstance(c, Nonterminal) and len(c.children))] symbol = extranode.symbol[5:] - if len(extranode.children) == 2: + if len(children) == 2: return child - right = extranode.children[2] + right = children[2] assert isinstance(right, Nonterminal) children = [child, self.transform(right.children[0]), From pedronis at codespeak.net Mon Dec 4 12:17:33 2006 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Mon, 4 Dec 2006 12:17:33 +0100 (CET) Subject: [pypy-svn] r35248 - pypy/dist/pypy/translator/backendopt Message-ID: <20061204111733.86F2D10074@code0.codespeak.net> Author: pedronis Date: Mon Dec 4 12:17:32 2006 New Revision: 35248 Modified: pypy/dist/pypy/translator/backendopt/mallocprediction.py Log: repair inconsistency Modified: pypy/dist/pypy/translator/backendopt/mallocprediction.py ============================================================================== --- pypy/dist/pypy/translator/backendopt/mallocprediction.py (original) +++ pypy/dist/pypy/translator/backendopt/mallocprediction.py Mon Dec 4 12:17:32 2006 @@ -133,7 +133,7 @@ tot = 0 if graphs is None: graphs = translator.graphs - for graph in translator.graphs: + for graph in graphs: count = remove_simple_mallocs(graph) if count: # remove typical leftovers from malloc removal From arigo at codespeak.net Mon Dec 4 12:24:53 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 4 Dec 2006 12:24:53 +0100 (CET) Subject: [pypy-svn] r35249 - in pypy/branch/jit-real-world/pypy: annotation jit/timeshifter jit/timeshifter/test Message-ID: <20061204112453.11A9710071@code0.codespeak.net> Author: arigo Date: Mon Dec 4 12:24:51 2006 New Revision: 35249 Modified: pypy/branch/jit-real-world/pypy/annotation/model.py pypy/branch/jit-real-world/pypy/jit/timeshifter/test/test_promotion.py pypy/branch/jit-real-world/pypy/jit/timeshifter/transform.py Log: Last check-in from yesterday night. Modified: pypy/branch/jit-real-world/pypy/annotation/model.py ============================================================================== --- pypy/branch/jit-real-world/pypy/annotation/model.py (original) +++ pypy/branch/jit-real-world/pypy/annotation/model.py Mon Dec 4 12:24:51 2006 @@ -606,8 +606,7 @@ if v is None: # i think we can only get here in the case of void-returning # functions - from pypy.annotation.bookkeeper import getbookkeeper - return getbookkeeper().immutablevalue(None) + return s_None if isinstance(v, MethodType): ll_ptrtype = lltype.typeOf(v.im_self) assert isinstance(ll_ptrtype, lltype.Ptr) Modified: pypy/branch/jit-real-world/pypy/jit/timeshifter/test/test_promotion.py ============================================================================== --- pypy/branch/jit-real-world/pypy/jit/timeshifter/test/test_promotion.py (original) +++ pypy/branch/jit-real-world/pypy/jit/timeshifter/test/test_promotion.py Mon Dec 4 12:24:51 2006 @@ -215,16 +215,20 @@ assert res == ll_function(6, 3, 2, 2) def test_green_across_global_mp(self): - def ll_function(n, total): - while n: + def ll_function(n1, n2, n3, n4, total): + while n2: hint(None, global_merge_point=True) - total += n - hint(n, concrete=True) - n -= 1 + total += n3 + hint(n4, concrete=True) + hint(n3, concrete=True) + hint(n2, concrete=True) + hint(n1, concrete=True) + n2 -= 1 return total - res = self.timeshift(ll_function, [5, 100], [0], policy=P_NOVIRTUAL) - assert res == 115 + res = self.timeshift(ll_function, [None, 4, 3, None, 100], [0], + policy=P_NOVIRTUAL) + assert res == ll_function(None, 4, 3, None, 100) def test_remembers_across_mp(self): def ll_function(x, flag): Modified: pypy/branch/jit-real-world/pypy/jit/timeshifter/transform.py ============================================================================== --- pypy/branch/jit-real-world/pypy/jit/timeshifter/transform.py (original) +++ pypy/branch/jit-real-world/pypy/jit/timeshifter/transform.py Mon Dec 4 12:24:51 2006 @@ -108,11 +108,12 @@ def graph_calling_color(self, tsgraph): args_hs, hs_res = self.hannotator.bookkeeper.tsgraphsigs[tsgraph] if originalconcretetype(hs_res) is lltype.Void: - return 'gray' + c = 'gray' elif hs_res.is_green(): - return 'yellow' + c = 'yellow' else: - return 'red' + c = 'red' + return c def timeshifted_graph_of(self, graph, args_v): bk = self.hannotator.bookkeeper @@ -349,6 +350,11 @@ N = self.get_resume_point(mergeblock) c_resumeindex = inputconst(lltype.Signed, N) self.genop(block, 'guard_global_merge', [c_resumeindex]) + + # Note: the jitstate.greens list will contain the correct + # green gv's for the following global_merge_point, because + # the green values have just been restored by the resume + # point logic here else: mergeblock = block greens2 = greens1 @@ -526,21 +532,29 @@ def handle_red_call(self, block, pos, color='red'): link = split_block(self.hannotator, block, pos+1) op = block.operations.pop(pos) + #if op.opname == 'direct_call': + # f = open('LOG', 'a') + # print >> f, color, op.args[0].value + # f.close() assert len(block.operations) == pos nextblock = link.target linkargs = link.args varsalive = list(linkargs) - + + if color == 'red': + assert not self.hannotator.binding(op.result).is_green() + try: index = varsalive.index(op.result) + except ValueError: + uses_retval = False + else: uses_retval = True # it will be restored by a restore_local del varsalive[index] old_v_result = linkargs.pop(index) linkargs.insert(0, old_v_result) v_result = nextblock.inputargs.pop(index) nextblock.inputargs.insert(0, v_result) - except ValueError: - uses_retval = False reds, greens = self.sort_by_color(varsalive) @@ -607,6 +621,10 @@ def handle_yellow_call(self, block, pos): op = block.operations[pos] + #if op.opname == 'direct_call': + # f = open('LOG', 'a') + # print >> f, 'handle_yellow_call', op.args[0].value + # f.close() hs_result = self.hannotator.binding(op.result) if not hs_result.is_green(): # yellow calls are supposed to return greens, From ericvrp at codespeak.net Mon Dec 4 12:48:42 2006 From: ericvrp at codespeak.net (ericvrp at codespeak.net) Date: Mon, 4 Dec 2006 12:48:42 +0100 (CET) Subject: [pypy-svn] r35251 - pypy/dist/pypy/jit/codegen/llvm Message-ID: <20061204114842.630671006C@code0.codespeak.net> Author: ericvrp Date: Mon Dec 4 12:48:41 2006 New Revision: 35251 Modified: pypy/dist/pypy/jit/codegen/llvm/rgenop.py Log: More code taken from jit/codegen/i386 Modified: pypy/dist/pypy/jit/codegen/llvm/rgenop.py ============================================================================== --- pypy/dist/pypy/jit/codegen/llvm/rgenop.py (original) +++ pypy/dist/pypy/jit/codegen/llvm/rgenop.py Mon Dec 4 12:48:41 2006 @@ -1,8 +1,250 @@ +from pypy.rlib.objectmodel import specialize from pypy.jit.codegen.model import AbstractRGenOp, GenLabel, GenBuilder from pypy.jit.codegen.model import GenVar, GenConst, CodeGenSwitch + +class Var(GenVar): + + def __init__(self): + pass + + #repr? + + +class IntConst(GenConst): + + def __init__(self, value): + self.value = value + + @specialize.arg(1) + def revealconst(self, T): + if isinstance(T, lltype.Ptr): + return lltype.cast_int_to_ptr(T, self.value) + elif T is llmemory.Address: + return llmemory.cast_int_to_adr(self.value) + else: + return lltype.cast_primitive(T, self.value) + + #repr? + + +class AddrConst(GenConst): + + def __init__(self, addr): + self.addr = addr + + @specialize.arg(1) + def revealconst(self, T): + if T is llmemory.Address: + return self.addr + elif isinstance(T, lltype.Ptr): + return llmemory.cast_adr_to_ptr(self.addr, T) + elif T is lltype.Signed: + return llmemory.cast_adr_to_int(self.addr) + else: + assert 0, "XXX not implemented" + + #repr? + + +class Label(GenLabel): + + def __init__(self, startaddr, arg_positions, stackdepth): + self.startaddr = startaddr + self.arg_positions = arg_positions + self.stackdepth = stackdepth + + +class FlexSwitch(CodeGenSwitch): + + # + + def __init__(self, rgenop): + self.rgenop = rgenop + self.default_case_addr = 0 + + def initialize(self, builder, gv_exitswitch): + mc = builder.mc + mc.MOV(eax, gv_exitswitch.operand(builder)) + self.saved_state = builder._save_state() + self._reserve(mc) + + def _reserve(self, mc): + RESERVED = 11*4+5 # XXX quite a lot for now :-/ + pos = mc.tell() + mc.UD2() + mc.write('\x00' * (RESERVED-1)) + self.nextfreepos = pos + self.endfreepos = pos + RESERVED + + def _reserve_more(self): + start = self.nextfreepos + end = self.endfreepos + newmc = self.rgenop.open_mc() + self._reserve(newmc) + self.rgenop.close_mc(newmc) + fullmc = InMemoryCodeBuilder(start, end) + fullmc.JMP(rel32(self.nextfreepos)) + fullmc.done() + + def add_case(self, gv_case): + rgenop = self.rgenop + targetbuilder = Builder._new_from_state(rgenop, self.saved_state) + target_addr = targetbuilder.mc.tell() + try: + self._add_case(gv_case, target_addr) + except CodeBlockOverflow: + self._reserve_more() + self._add_case(gv_case, target_addr) + return targetbuilder + + def _add_case(self, gv_case, target_addr): + start = self.nextfreepos + end = self.endfreepos + mc = InMemoryCodeBuilder(start, end) + mc.CMP(eax, gv_case.operand(None)) + mc.JE(rel32(target_addr)) + pos = mc.tell() + if self.default_case_addr: + mc.JMP(rel32(self.default_case_addr)) + else: + illegal_start = mc.tell() + mc.JMP(rel32(0)) + ud2_addr = mc.tell() + mc.UD2() + illegal_mc = InMemoryCodeBuilder(illegal_start, end) + illegal_mc.JMP(rel32(ud2_addr)) + mc.done() + self.nextfreepos = pos + + def add_default(self): + rgenop = self.rgenop + targetbuilder = Builder._new_from_state(rgenop, self.saved_state) + self.default_case_addr = targetbuilder.mc.tell() + start = self.nextfreepos + end = self.endfreepos + mc = InMemoryCodeBuilder(start, end) + mc.JMP(rel32(self.default_case_addr)) + mc.done() + return targetbuilder + + # + + +class Builder(GenBuilder): + + def __init__(self, rgenop): + self.rgenop = rgenop + + # ---------------------------------------------------------------- + # The public Builder interface + + def end(self): + pass + + @specialize.arg(1) + def genop1(self, opname, gv_arg): + genmethod = getattr(self, 'op_' + opname) + return genmethod(gv_arg) + + @specialize.arg(1) + def genop2(self, opname, gv_arg1, gv_arg2): + genmethod = getattr(self, 'op_' + opname) + return genmethod(gv_arg1, gv_arg2) + + + class RLLVMGenOp(AbstractRGenOp): - pass + + def __init__(self): + #self.mcs = [] # machine code blocks where no-one is currently writing + #self.keepalive_gc_refs = [] + pass + + # ---------------------------------------------------------------- + # the public RGenOp interface + + def openbuilder(self): + return Builder(self) + + def newgraph(self, sigtoken, name): + numargs = sigtoken # for now + builder = self.openbuilder() + entrypoint = builder.asm.mc.tell() + inputargs_gv = builder._write_prologue(sigtoken) + return builder, IntConst(entrypoint), inputargs_gv + + @specialize.genconst(1) + def genconst(self, llvalue): #i386 version (ppc version is slightly different) + T = lltype.typeOf(llvalue) + if T is llmemory.Address: + return AddrConst(llvalue) + elif isinstance(T, lltype.Primitive): + return IntConst(lltype.cast_primitive(lltype.Signed, llvalue)) + elif isinstance(T, lltype.Ptr): + lladdr = llmemory.cast_ptr_to_adr(llvalue) + if T.TO._gckind == 'gc': + self.keepalive_gc_refs.append(lltype.cast_opaque_ptr(llmemory.GCREF, llvalue)) + return AddrConst(lladdr) + else: + assert 0, "XXX not implemented" + + # attached later constPrebuiltGlobal = global_rgenop.genconst + + @staticmethod + @specialize.memo() + def fieldToken(T, name): + return llmemory.offsetof(T, name) + + @staticmethod + @specialize.memo() + def allocToken(T): + return llmemory.sizeof(T) + + @staticmethod + @specialize.memo() + def varsizeAllocToken(T): + if isinstance(T, lltype.Array): + return RI386GenOp.arrayToken(T) + else: + # var-sized structs + arrayfield = T._arrayfld + ARRAYFIELD = getattr(T, arrayfield) + arraytoken = RI386GenOp.arrayToken(ARRAYFIELD) + length_offset, items_offset, item_size = arraytoken + arrayfield_offset = llmemory.offsetof(T, arrayfield) + return (arrayfield_offset+length_offset, + arrayfield_offset+items_offset, + item_size) + + @staticmethod + @specialize.memo() + def arrayToken(A): + return (llmemory.ArrayLengthOffset(A), + llmemory.ArrayItemsOffset(A), + llmemory.ItemOffset(A.OF)) + + @staticmethod + @specialize.memo() + def kindToken(T): + return None # for now + + @staticmethod + @specialize.memo() + def sigToken(FUNCTYPE): + return len(FUNCTYPE.ARGS) # for now + + @staticmethod + def erasedType(T): + if T is llmemory.Address: + return llmemory.Address + if isinstance(T, lltype.Primitive): + return lltype.Signed + elif isinstance(T, lltype.Ptr): + return llmemory.GCREF + else: + assert 0, "XXX not implemented" + global_rgenop = RLLVMGenOp() -#XXX RLLVMGenOp.constPrebuiltGlobal = global_rgenop.genconst +RLLVMGenOp.constPrebuiltGlobal = global_rgenop.genconst From cfbolz at codespeak.net Mon Dec 4 13:40:35 2006 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Mon, 4 Dec 2006 13:40:35 +0100 (CET) Subject: [pypy-svn] r35252 - pypy/branch/guido-config-testing Message-ID: <20061204124035.80F4D10064@code0.codespeak.net> Author: cfbolz Date: Mon Dec 4 13:40:33 2006 New Revision: 35252 Removed: pypy/branch/guido-config-testing/ Log: remove dead branch From auc at codespeak.net Mon Dec 4 14:30:37 2006 From: auc at codespeak.net (auc at codespeak.net) Date: Mon, 4 Dec 2006 14:30:37 +0100 (CET) Subject: [pypy-svn] r35253 - pypy/dist/pypy/objspace/test Message-ID: <20061204133037.A3BEC10064@code0.codespeak.net> Author: auc Date: Mon Dec 4 14:30:35 2006 New Revision: 35253 Added: pypy/dist/pypy/objspace/test/problems.py - copied unchanged from r32835, pypy/dist/pypy/objspace/constraint/applevel/problems.py Modified: pypy/dist/pypy/objspace/test/_test_logic_build.py pypy/dist/pypy/objspace/test/test_logicobjspace.py Log: test fixes Modified: pypy/dist/pypy/objspace/test/_test_logic_build.py ============================================================================== --- pypy/dist/pypy/objspace/test/_test_logic_build.py (original) +++ pypy/dist/pypy/objspace/test/_test_logic_build.py Mon Dec 4 14:30:35 2006 @@ -24,7 +24,7 @@ for name, meth in inspect.getmembers(klass()) if not name.startswith('_')] -def run_tests(tm): +def run_tests(tm, selected_tests): tm.raises = raises tm.skip = skip @@ -32,13 +32,18 @@ successes = [] failures = [] skipped = [] - - for tests in [get_test_methods(cl) for cl in get_test_classes()] : + all_tests = [get_test_methods(cl) for cl in get_test_classes()] + print "testing %s test(s) classe(s)" % len(all_tests) + for tests in all_tests: for name, meth in tests: if name == 'setup_class': continue + if selected_tests and name not in selected_tests: + continue try: meth() except Skip: +## import traceback +## traceback.print_exc() skipped.append(name) except Exception, e: failures.append((name, meth, e)) @@ -66,4 +71,9 @@ if __name__ == __name__: import sys tm = __import__(sys.argv[1]) - run_tests(tm) + tests = [] + try: + tests += (sys.argv[2:]) + except: + pass + run_tests(tm, tests) Modified: pypy/dist/pypy/objspace/test/test_logicobjspace.py ============================================================================== --- pypy/dist/pypy/objspace/test/test_logicobjspace.py (original) +++ pypy/dist/pypy/objspace/test/test_logicobjspace.py Mon Dec 4 14:30:35 2006 @@ -438,7 +438,9 @@ assert len(sched_info()['blocked_byneed']) == 1 reset_scheduler() assert len(sched_info()['blocked_byneed']) == 0 - assert len(sched_info().values()[0]['threads']) == 1 + sp_info = [y for x, y in sched_info().items() + if isinstance(x, int)][0] + assert len(sp_info['threads']) == 1 def test_wait_two(self): @@ -461,7 +463,9 @@ unify(Y, 42) assert X == Y == 42 assert o == 2 - assert len(sched_info().values()[0]['threads']) == 1 + sp_info = [y for x, y in sched_info().items() + if isinstance(x, int)][0] + assert len(sp_info['threads']) == 1 def test_fib(self): def fib(X): @@ -498,14 +502,17 @@ assert count[0] == max_spawn + erring try: wait(Failed) - except RebindingError, e: - assert len(sched_info().values()[0]['threads']) == 1 + except RebindingError, e: + sp_info = [y for x, y in sched_info().items() + if isinstance(x, int)][0] + assert len(sp_info['threads']) == 1 return assert False def test_nd_append(self): skip("non determnistic choice: yet to come") #from CTM p.639 + #write me correctly... """ def append(A, B, C): choice: @@ -793,9 +800,10 @@ def test_default_solver(self): - skip("segfaulting") if is_interpreted(): skip("will loop infinitely (bug in space.clone())") + else: + skip("clone segfaults") from constraint.examples import conference_scheduling from constraint import solver @@ -878,9 +886,7 @@ solve(s, commit_to, Solution) assert Solution in (False, ('beige', 'mauve', 'coral')) - def test_queens1(self): - if not is_interpreted(): - skip("segfaulting") + def test_queens(self): from constraint.examples import queens1, queens2 def solve(spc, commitment, Sol): @@ -919,3 +925,20 @@ if Solution: sols.add(tuple(Solution)) assert len(sols) == 2 + + + def test_cloning_queens(self): + if is_interpreted(): + skip("no cloning feature") + from constraint.examples import queens1, queens2 + from constraint.solver import solve + + #switch_debug_info() + for queen in (queens1,):# queens2): + sols = set() + s = newspace(queens1, {'size':8}) + for sol in solve(s): + sols.add(sol) + print sol + #assert len(sols) == 2 + From antocuni at codespeak.net Mon Dec 4 16:06:13 2006 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Mon, 4 Dec 2006 16:06:13 +0100 (CET) Subject: [pypy-svn] r35256 - in pypy/dist/pypy: bin objspace/fake objspace/fake/test translator Message-ID: <20061204150613.2E15A1006E@code0.codespeak.net> Author: antocuni Date: Mon Dec 4 16:06:12 2006 New Revision: 35256 Added: pypy/dist/pypy/bin/checkmodule.py (contents, props changed) pypy/dist/pypy/objspace/fake/ pypy/dist/pypy/objspace/fake/__init__.py (contents, props changed) pypy/dist/pypy/objspace/fake/checkmodule.py (contents, props changed) pypy/dist/pypy/objspace/fake/objspace.py (contents, props changed) pypy/dist/pypy/objspace/fake/test/ pypy/dist/pypy/objspace/fake/test/__init__.py (contents, props changed) pypy/dist/pypy/objspace/fake/test/test_checkmodule.py (contents, props changed) Modified: pypy/dist/pypy/translator/driver.py Log: First version of the Fake object space and the checkmodule.py tool, which is useful for checking whether a module compiles without the need of a full translation. checkmodule is far from being complete: so far the only module known to pass is _dotnet. Added: pypy/dist/pypy/bin/checkmodule.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/bin/checkmodule.py Mon Dec 4 16:06:12 2006 @@ -0,0 +1,38 @@ +#! /usr/bin/env python +""" +Usage: checkmodule.py [-b backend] + +Compiles the PyPy extension module from pypy/module// +into a fake program which does nothing. Useful for testing whether a +modules compiles without doing a full translation, especially the ones +that cannot be compiled with compilemodule.py because rely on +ootypesystem features (such as _dotnet). Default backend is cli. + +WARNING: this is still incomplete: there are chances that the +compilation fails with strange errors not due to the module. If a +module is known to compile during a translation but don't pass +checkmodule.py, please report the bug (or, better, correct it :-). +""" +import autopath +import sys + +from pypy.objspace.fake.checkmodule import checkmodule + +def main(argv): + try: + assert len(argv) in (2, 4) + if len(argv) == 2: + backend = 'cli' + modname = argv[1] + else: + _, b, backend, modname = argv + assert b == '-b' + except AssertionError: + print >> sys.stderr, __doc__ + sys.exit(2) + else: + checkmodule(modname, backend, interactive=True) + print 'Module compiled succesfully' + +if __name__ == '__main__': + main(sys.argv) Added: pypy/dist/pypy/objspace/fake/__init__.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/objspace/fake/__init__.py Mon Dec 4 16:06:12 2006 @@ -0,0 +1,2 @@ +from objspace import FakeObjSpace +Space = FakeObjSpace Added: pypy/dist/pypy/objspace/fake/checkmodule.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/objspace/fake/checkmodule.py Mon Dec 4 16:06:12 2006 @@ -0,0 +1,102 @@ +from copy import copy +from pypy.tool.error import debug +from pypy.interpreter.argument import AbstractArguments +from pypy.interpreter.gateway import interp2app +from pypy.rlib.nonconst import NonConstant + +def my_import(name): + mod = __import__(name) + components = name.split('.') + for comp in components[1:]: + mod = getattr(mod, comp) + return mod + +def find_gateways(modname, basepath, module): + res = [] + for name in module.interpleveldefs.values(): + submod_name, obj_name = name.split('.') + submod_name = '%s.%s.%s' % (basepath, modname, submod_name) + submod = my_import(submod_name) + obj = getattr(submod, obj_name) + res += find_gw_in_obj(obj) + return res + +def find_gw_in_obj(obj): + if hasattr(obj, 'typedef'): + typedef = obj.typedef + return typedef.rawdict.values() # XXX: check they are interp2app + elif hasattr(obj, 'func_code'): + return [interp2app(obj)] + else: + assert False + +## Since the fake objspace is more a hack than a real object space, it +## happens that the annotator complains about operations that cannot +## succeed because it knows too much about the objects involved. For +## example, if it knows that a list is always empty, it will block +## each operations that tries to access that list. This is not what we +## want, because we know that with real objectspaces that operations +## will succeed. + +## As a workaround, we insert dummy rpython code (the function +## dummy_rpython) that manipulates the variables in order to give +## them a more sensible annotation. This is the preferred way to solve +## the problems so far. + +## If the solution above doesn't work, the alternative is to +## substitute the interpreter code with something that doesn't hurt +## the annotator. It's a very ugly hack, better solutions are welcome +## :-) + + +# dummy rpython code to give some variables more sensible annotations +def dummy_rpython(dummy_function): + # to make the annotator flow-in without executing the code + if NonConstant(False): + dummy_function.defs_w = [None] # else the annotator would see an always empty list + +def patch_pypy(): + from pypy.interpreter.baseobjspace import W_Root + + def descr_call_mismatch(self, space, opname, RequiredClass, args): + from pypy.interpreter.error import OperationError + msg = 'This message will never be displayed :-)' + raise OperationError(space.w_TypeError, space.wrap(msg)) + W_Root.descr_call_mismatch = descr_call_mismatch + + +def checkmodule(modname, backend, interactive=False, basepath='pypy.module'): + "Compile a fake PyPy module." + from pypy.objspace.fake.objspace import FakeObjSpace, W_Object + from pypy.translator.driver import TranslationDriver + + space = FakeObjSpace() + space.config.translating = True + ModuleClass = __import__(basepath + '.%s' % modname, + None, None, ['Module']).Module + module = ModuleClass(space, space.wrap(modname)) + w_moduledict = module.getdict() + + gateways = find_gateways(modname, basepath, module) + functions = [gw.__spacebind__(space) for gw in gateways] + arguments = AbstractArguments.frompacked(space, W_Object(None), W_Object(None)) + dummy_function = copy(functions[0]) + + def main(argv): # use the standalone mode not to allow SomeObject + dummy_rpython(dummy_function) + for func in functions: + func.call_args(arguments) + return 0 + + patch_pypy() + driver = TranslationDriver() + driver.setup(main, None) + try: + driver.proceed(['compile_' + backend]) + except SystemExit: + raise + except: + if not interactive: + raise + debug(driver) + raise SystemExit(1) Added: pypy/dist/pypy/objspace/fake/objspace.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/objspace/fake/objspace.py Mon Dec 4 16:06:12 2006 @@ -0,0 +1,144 @@ +from pypy.interpreter.baseobjspace import ObjSpace, Wrappable, W_Root +from pypy.rlib.nonconst import NonConstant +from pypy.rlib.rarithmetic import r_uint + +class W_Type(W_Root): + pass + +class W_Object(W_Root): + def __init__(self, value): + self.value = value +W_Object.typedef = W_Type() + +def make_dummy(a=W_Object(None), b=W_Object(None)): + def fn(*args): + if NonConstant(True): + return a + else: + return b + return fn + +int_dummy = make_dummy(42, 43) +float_dummy = make_dummy(42.0, 42.1) +uint_dummy = make_dummy(r_uint(42), r_uint(43)) +str_dummy = make_dummy('foo', 'bar') +bool_dummy = make_dummy(True, False) + +class FakeObjSpace(ObjSpace): + w_None = W_Object(None) + w_False = W_Object(None) + w_True = W_Object(None) + w_Ellipsis = W_Object(None) + w_NotImplemented = W_Object(None) + w_int = W_Object(None) + w_dict = W_Object(None) + w_float = W_Object(None) + w_long = W_Object(None) + w_tuple = W_Object(None) + w_str = W_Object(None) + w_unicode = W_Object(None) + w_type = W_Object(None) + w_instance = W_Object(None) + w_slice = W_Object(None) + w_hex = W_Object(None) + w_oct = W_Object(None) + + def initialize(self): + self.config.objspace.geninterp = False + self.wrap_cache = {} + self.make_builtins() + + def _freeze_(self): + return True + + def wrap(self, x): + if isinstance(x, Wrappable): + w_result = x.__spacebind__(self) + return w_result + return W_Object(x) + wrap._annspecialcase_ = "specialize:argtype(1)" + + def unwrap(self, w_obj): + assert isinstance(w_obj, W_Object) + return w_obj.value + + lookup = make_dummy() + allocate_instance = make_dummy() + getattr = make_dummy() + setattr = make_dummy() + getitem = make_dummy() + setitem = make_dummy() + delitem = make_dummy() + int_w = int_dummy + uint_w = uint_dummy + float_w = float_dummy + iter = make_dummy() + type = make_dummy() + str = make_dummy() + repr = make_dummy() + id = make_dummy() + len = make_dummy() + str_w = str_dummy + call_args = make_dummy() + new_interned_str = make_dummy() + newstring = make_dummy() + newunicode = make_dummy() + newint = make_dummy() + newlong = make_dummy() + newfloat = make_dummy() + newdict = make_dummy() + newlist = make_dummy() + emptylist = make_dummy() + newtuple = make_dummy() + newslice = make_dummy() + lt = make_dummy() + le = make_dummy() + eq = make_dummy() + ne = make_dummy() + gt = make_dummy() + ge = make_dummy() + lt_w = bool_dummy + le_w = bool_dummy + eq_w = bool_dummy + ne_w = bool_dummy + gt_w = bool_dummy + ge_w = bool_dummy + is_w = bool_dummy + is_ = make_dummy() + next = make_dummy() + is_true = bool_dummy + nonzero = make_dummy() + issubtype = make_dummy() + ord = make_dummy() + hash = make_dummy() + delattr = make_dummy() # should return None? + contains = make_dummy() + hex = make_dummy() + oct = make_dummy() + pow = make_dummy() + inplace_pow = make_dummy() + cmp = make_dummy() + + # XXsX missing operations + def coerce(self, *args): raise NotImplementedError("space.coerce()") + def get(self, *args): raise NotImplementedError("space.get()") + def set(self, *args): raise NotImplementedError("space.set()") + def delete(self, *args): raise NotImplementedError("space.delete()") + def userdel(self, *args): raise NotImplementedError("space.userdel()") + def marshal_w(self, *args):raise NotImplementedError("space.marshal_w()") + def log(self, *args): raise NotImplementedError("space.log()") + + def exec_(self, statement, w_globals, w_locals, hidden_applevel=False): + "NOT_RPYTHON" + raise NotImplementedError("space.exec_") + + gettypefor = make_dummy() + gettypeobject = make_dummy() + unpackiterable = make_dummy([W_Object(None)], [W_Object(None)]) + + +## Register all exceptions +import exceptions +for name in ObjSpace.ExceptionTable: + exc = getattr(exceptions, name) + setattr(FakeObjSpace, 'w_' + name, W_Object(None)) Added: pypy/dist/pypy/objspace/fake/test/__init__.py ============================================================================== Added: pypy/dist/pypy/objspace/fake/test/test_checkmodule.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/objspace/fake/test/test_checkmodule.py Mon Dec 4 16:06:12 2006 @@ -0,0 +1,6 @@ +import py +from pypy.objspace.fake.checkmodule import checkmodule + +def test_dotnet(): + # the only module known to pass checkmodule is _dotnet so far + checkmodule('_dotnet', 'cli') Modified: pypy/dist/pypy/translator/driver.py ============================================================================== --- pypy/dist/pypy/translator/driver.py (original) +++ pypy/dist/pypy/translator/driver.py Mon Dec 4 16:06:12 2006 @@ -7,6 +7,7 @@ from pypy.annotation.listdef import s_list_of_strings from pypy.annotation import policy as annpolicy from py.compat import optparse +from pypy.tool.udir import udir import py from pypy.tool.ansi_print import ansi_log @@ -563,7 +564,6 @@ def task_source_cli(self): from pypy.translator.cli.gencli import GenCli from pypy.translator.cli.entrypoint import get_entrypoint - from pypy.tool.udir import udir entry_point_graph = self.translator.graphs[0] self.gen = GenCli(udir, self.translator, get_entrypoint(entry_point_graph), @@ -579,7 +579,8 @@ filename = self.gen.build_exe() self.c_entryp = CliFunctionWrapper(filename) # restore original os values - unpatch(*self.old_cli_defs) + if hasattr(self, 'old_cli_defs'): + unpatch(*self.old_cli_defs) self.log.info("Compiled %s" % filename) task_compile_cli = taskdef(task_compile_cli, ['source_cli'], From antocuni at codespeak.net Mon Dec 4 16:47:06 2006 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Mon, 4 Dec 2006 16:47:06 +0100 (CET) Subject: [pypy-svn] r35258 - pypy/dist/pypy/rpython/ootypesystem Message-ID: <20061204154706.E0FE910077@code0.codespeak.net> Author: antocuni Date: Mon Dec 4 16:47:05 2006 New Revision: 35258 Modified: pypy/dist/pypy/rpython/ootypesystem/rclass.py Log: Sorry, forgot this in the last check-in. Modified: pypy/dist/pypy/rpython/ootypesystem/rclass.py ============================================================================== --- pypy/dist/pypy/rpython/ootypesystem/rclass.py (original) +++ pypy/dist/pypy/rpython/ootypesystem/rclass.py Mon Dec 4 16:47:05 2006 @@ -207,7 +207,7 @@ else: s_value = attrdef.s_value if isinstance(s_value, annmodel.SomePBC): - if s_value.getKind() == description.MethodDesc: + if len(s_value.descriptions) > 0 and s_value.getKind() == description.MethodDesc: # attrdef is for a method if mangled in allclassattributes: raise TyperError("method overrides class attribute") From auc at codespeak.net Mon Dec 4 18:25:16 2006 From: auc at codespeak.net (auc at codespeak.net) Date: Mon, 4 Dec 2006 18:25:16 +0100 (CET) Subject: [pypy-svn] r35263 - pypy/dist/pypy/objspace/test Message-ID: <20061204172516.B01F310071@code0.codespeak.net> Author: auc Date: Mon Dec 4 18:25:15 2006 New Revision: 35263 Modified: pypy/dist/pypy/objspace/test/test_logicobjspace.py Log: skip test Modified: pypy/dist/pypy/objspace/test/test_logicobjspace.py ============================================================================== --- pypy/dist/pypy/objspace/test/test_logicobjspace.py (original) +++ pypy/dist/pypy/objspace/test/test_logicobjspace.py Mon Dec 4 18:25:15 2006 @@ -887,6 +887,7 @@ assert Solution in (False, ('beige', 'mauve', 'coral')) def test_queens(self): + skip("success depends on dict order") from constraint.examples import queens1, queens2 def solve(spc, commitment, Sol): From cfbolz at codespeak.net Mon Dec 4 20:07:01 2006 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Mon, 4 Dec 2006 20:07:01 +0100 (CET) Subject: [pypy-svn] r35265 - pypy/dist/pypy/doc Message-ID: <20061204190701.A6F0310077@code0.codespeak.net> Author: cfbolz Date: Mon Dec 4 20:06:59 2006 New Revision: 35265 Modified: pypy/dist/pypy/doc/video-index.txt Log: add a link to the videos on 1dawg Modified: pypy/dist/pypy/doc/video-index.txt ============================================================================== --- pypy/dist/pypy/doc/video-index.txt (original) +++ pypy/dist/pypy/doc/video-index.txt Mon Dec 4 20:06:59 2006 @@ -19,9 +19,13 @@ have a video player that supports DivX AVI files (DivX 5, mp3 audio) such as `mplayer`_, `xine`_, `vlc`_ or the windows media player. +The videos are also available on the "1Dawg" video conversion service, +`tagged with pypy`_. Thanks to johnjay for putting them there. + .. _`mplayer`: http://www.mplayerhq.hu/design7/dload.html .. _`xine`: http://xinehq.de/index.php/releases .. _`vlc`: http://www.videolan.org/vlc/ +.. _`tagged with pypy`: http://1dawg.com/tagged/pypy You can find the necessary codecs in the ffdshow-library: http://ffdshow.sourceforge.net/tikiwiki/tiki-index.php From cfbolz at codespeak.net Mon Dec 4 20:12:31 2006 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Mon, 4 Dec 2006 20:12:31 +0100 (CET) Subject: [pypy-svn] r35266 - in pypy/dist/pypy: config config/test interpreter tool tool/build translator translator/c translator/c/test translator/cli translator/goal translator/js translator/llvm translator/oosupport translator/test Message-ID: <20061204191231.A91511007A@code0.codespeak.net> Author: cfbolz Date: Mon Dec 4 20:12:22 2006 New Revision: 35266 Added: pypy/dist/pypy/config/translationoption.py Modified: pypy/dist/pypy/config/pypyoption.py pypy/dist/pypy/config/test/test_pypyoption.py pypy/dist/pypy/interpreter/baseobjspace.py pypy/dist/pypy/tool/build/config.py pypy/dist/pypy/tool/option.py pypy/dist/pypy/translator/c/genc.py pypy/dist/pypy/translator/c/test/test_boehm.py pypy/dist/pypy/translator/c/test/test_newgc.py pypy/dist/pypy/translator/c/test/test_stackless.py pypy/dist/pypy/translator/c/test/test_typed.py pypy/dist/pypy/translator/cli/gencli.py pypy/dist/pypy/translator/driver.py pypy/dist/pypy/translator/goal/targetpypystandalone.py pypy/dist/pypy/translator/goal/translate.py pypy/dist/pypy/translator/interactive.py pypy/dist/pypy/translator/js/main.py pypy/dist/pypy/translator/llvm/genllvm.py pypy/dist/pypy/translator/oosupport/genoo.py pypy/dist/pypy/translator/test/test_driver.py pypy/dist/pypy/translator/translator.py Log: steps into the direction of separating the translation from the pypy options. Some messes involved. Modified: pypy/dist/pypy/config/pypyoption.py ============================================================================== --- pypy/dist/pypy/config/pypyoption.py (original) +++ pypy/dist/pypy/config/pypyoption.py Mon Dec 4 20:12:22 2006 @@ -18,220 +18,112 @@ module_dependencies['rctime'] = [("objspace.usemodules.select", True),] -pypy_optiondescription = OptionDescription("pypy", "All PyPy Options", [ - OptionDescription("objspace", "Object Space Option", [ - ChoiceOption("name", "Object Space name", - ["std", "flow", "logic", "thunk", "cpy", "dump", "sand"], - "std", - requires = { - "logic": [("objspace.geninterp", False), - ("objspace.usemodules._stackless", True)], - }, - cmdline='--objspace -o'), - - ChoiceOption("parser", "parser", - ["pypy", "cpython"], "pypy", - cmdline='--parser'), - - ChoiceOption("compiler", "compiler", - ["cpython", "ast"], "ast", - cmdline='--compiler'), +pypy_optiondescription = OptionDescription("objspace", "Object Space Option", [ + ChoiceOption("name", "Object Space name", + ["std", "flow", "logic", "thunk", "cpy", "dump"], "std", + requires = { + "thunk": [("objspace.geninterp", False)], + "logic": [("objspace.geninterp", False), + ("objspace.usemodules._stackless", True)], + }, + cmdline='--objspace -o'), + + ChoiceOption("parser", "parser", + ["pypy", "cpython"], "pypy", + cmdline='--parser'), + + ChoiceOption("compiler", "compiler", + ["cpython", "ast"], "ast", + cmdline='--compiler'), + + BoolOption("nofaking", "disallow faking in the object space", + default=False, + requires=[ + ("objspace.usemodules.posix", True), + ("objspace.usemodules.time", True), + ("objspace.usemodules.errno", True)], + cmdline='--nofaking'), + + OptionDescription("usemodules", "Which Modules should be used", [ + BoolOption(modname, "use module %s" % (modname, ), + default=modname in default_modules, + cmdline="--withmod-%s" % (modname, ), + requires= module_dependencies.get(modname, [])) + for modname in all_modules]), + + BoolOption("geninterp", "specify whether geninterp should be used", + default=True), + + BoolOption("logbytecodes", + "keep track of bytecode usage", + default=False), + + BoolOption("usepycfiles", "Write and read pyc files when importing", + default=True), + + OptionDescription("std", "Standard Object Space Options", [ + BoolOption("withtproxy", "support transparent proxies", + default=False, cmdline='--with-transparent-proxy'), - BoolOption("nofaking", "disallow faking in the object space", + BoolOption("withsmallint", "use tagged integers", + default=False), + + BoolOption("withprebuiltint", "prebuilt commonly used int objects", default=False, - requires=[ - ("objspace.usemodules.posix", True), - ("objspace.usemodules.time", True), - ("objspace.usemodules.errno", True)], - cmdline='--nofaking'), - - OptionDescription("usemodules", "Which Modules should be used", [ - BoolOption(modname, "use module %s" % (modname, ), - default=modname in default_modules, - cmdline="--withmod-%s" % (modname, ), - requires= module_dependencies.get(modname, [])) - for modname in all_modules]), + requires=[("objspace.std.withsmallint", False)]), + + IntOption("prebuiltintfrom", "lowest integer which is prebuilt", + default=-5, cmdline="--prebuiltinfrom"), + + IntOption("prebuiltintto", "highest integer which is prebuilt", + default=100, cmdline="--prebuiltintto"), - BoolOption("geninterp", "specify whether geninterp should be used", - default=True), + BoolOption("withstrjoin", "use strings optimized for addition", + default=False), + + BoolOption("withstrslice", "use strings optimized for slicing", + default=False), - BoolOption("logbytecodes", - "keep track of bytecode usage", + BoolOption("withstrdict", + "use dictionaries optimized for string keys", default=False), - BoolOption("usepycfiles", "Write and read pyc files when importing", - default=True), - - OptionDescription("std", "Standard Object Space Options", [ - BoolOption("withtproxy", "support transparent proxies", - default=False, cmdline='--with-transparent-proxy'), - - BoolOption("withsmallint", "use tagged integers", - default=False), - - BoolOption("withprebuiltint", "prebuilt commonly used int objects", - default=False, - requires=[("objspace.std.withsmallint", False)]), - - IntOption("prebuiltintfrom", "lowest integer which is prebuilt", - default=-5, cmdline="--prebuiltinfrom"), - - IntOption("prebuiltintto", "highest integer which is prebuilt", - default=100, cmdline="--prebuiltintto"), - - BoolOption("withstrjoin", "use strings optimized for addition", - default=False), - - BoolOption("withstrslice", "use strings optimized for slicing", - default=False), - - BoolOption("withstrdict", - "use dictionaries optimized for string keys", - default=False), - - BoolOption("withmultidict", - "use dictionaries optimized for flexibility", - default=False, - requires=[("objspace.std.withstrdict", False)]), - - BoolOption("withdictmeasurement", - "create huge files with masses of information " - "about dictionaries", - default=False, - requires=[("objspace.std.withmultidict", True)]), - - BoolOption("withrangelist", - "enable special range list implementation that does not " - "actually create the full list until the resulting " - "list is mutaged", - default=False), - - BoolOption("oldstyle", - "specify whether the default metaclass should be classobj", - default=False, cmdline="--oldstyle"), - ]), - BoolOption("lowmem", "Try to use little memory during translation", - default=False, cmdline="--lowmem", - requires=[("objspace.geninterp", False)]), - - - ]), - - BoolOption("translating", "indicates whether we are translating currently", - default=False, cmdline=None), - - OptionDescription("translation", "Translation Options", [ - BoolOption("stackless", "compile stackless features in", - default=False, cmdline="--stackless", - requires=[("translation.type_system", "lltype")]), - ChoiceOption("type_system", "Type system to use when RTyping", - ["lltype", "ootype"], cmdline=None), - ChoiceOption("backend", "Backend to use for code generation", - ["c", "llvm", "cli", "js", "squeak", "cl"], - requires={ - "c": [("translation.type_system", "lltype")], - "llvm": [("translation.type_system", "lltype"), - ("translation.gc", "boehm"), - ("translation.backendopt.raisingop2direct_call", True)], - "cli": [("translation.type_system", "ootype")], - "js": [("translation.type_system", "ootype")], - "squeak": [("translation.type_system", "ootype")], - "cl": [("translation.type_system", "ootype")], - }, - cmdline="-b --backend"), - ChoiceOption("gc", "Garbage Collection Strategy", - ["boehm", "ref", "framework", "none", "stacklessgc", - "exact_boehm"], - "boehm", requires={ - "stacklessgc": [("translation.stackless", True)]}, - cmdline="--gc"), - BoolOption("thread", "enable use of threading primitives", - default=False, cmdline="--thread"), - BoolOption("verbose", "Print extra information", default=False), - BoolOption("debug", "Record extra annotation information", - cmdline="-d --debug", default=False), - BoolOption("insist", "Try hard to go on RTyping", default=False, - cmdline="--insist"), - BoolOption("countmallocs", "Count mallocs and frees", default=False, - cmdline=None), - - # misc - StrOption("cc", "Specify compiler", cmdline="--cc"), - StrOption("profopt", "Specify profile based optimization script", - cmdline="--profopt"), - BoolOption("debug_transform", "Perform the debug transformation", - default=False, cmdline="--debug-transform", negation=False), - - BoolOption("instrument", "internal: turn instrumentation on", - default=False, cmdline=None), - - ArbitraryOption("instrumentctl", "internal", - default=None), - - # portability options - BoolOption("vanilla", - "Try to be as portable as possible, which is not much", + BoolOption("withmultidict", + "use dictionaries optimized for flexibility", default=False, - cmdline="--vanilla", - requires=[("translation.no__thread", True)]), - BoolOption("no__thread", - "don't use __thread for implementing TLS", - default=False, cmdline="--no__thread", negation=False), - StrOption("compilerflags", "Specify flags for the compiler", - cmdline="--cflags"), - StrOption("linkerflags", "Specify flags for the linker", - cmdline="--ldflags"), - - # Flags of the TranslationContext: - BoolOption("simplifying", "Simplify flow graphs", default=True), - BoolOption("do_imports_immediately", "XXX", default=True, - cmdline=None), - BoolOption("builtins_can_raise_exceptions", "XXX", default=False, - cmdline=None), - BoolOption("list_comprehension_operations", "XXX", default=False, - cmdline=None), - ChoiceOption("fork_before", - "(UNIX) Create restartable checkpoint before step", - ["annotate", "rtype", "backendopt", "database", "source"], - default=None, cmdline="--fork-before"), - - OptionDescription("backendopt", "Backend Optimization Options", [ - BoolOption("print_statistics", "Print statistics while optimizing", - default=False), - BoolOption("merge_if_blocks", "Merge if ... elif chains", - cmdline="--if-block-merge", default=True), - BoolOption("raisingop2direct_call", - "Transform exception raising operations", - default=False, cmdline="--raisingop2direct_call"), - BoolOption("mallocs", "Remove mallocs", default=True), - BoolOption("constfold", "Constant propagation", - default=True), - BoolOption("heap2stack", "Escape analysis and stack allocation", - default=False, - requires=[("translation.stackless", False)]), - BoolOption("clever_malloc_removal", - "Remove mallocs in a clever way", default=False), - BoolOption("remove_asserts", - "Kill 'raise AssertionError', which lets the C " - "optimizer remove the asserts", default=False), - IntOption("inline_threshold", "Threshold when to inline functions", - default=1, cmdline=None), - StrOption("profile_based_inline", - "Use call count profiling to drive inlining" - ", specify arguments", - default=None, cmdline="--prof-based-inline"), - ]), - - OptionDescription("cli", "GenCLI options", [ - BoolOption("trace_calls", "Trace function calls", default=False, - cmdline="--cli-trace-calls") - ]), - ]), + requires=[("objspace.std.withstrdict", False)]), + + BoolOption("withdictmeasurement", + "create huge files with masses of information " + "about dictionaries", + default=False, + requires=[("objspace.std.withmultidict", True)]), + + BoolOption("withrangelist", + "enable special range list implementation that does not " + "actually create the full list until the resulting " + "list is mutaged", + default=False), + + BoolOption("oldstyle", + "specify whether the default metaclass should be classobj", + default=False, cmdline="--oldstyle"), + ]), + BoolOption("lowmem", "Try to use little memory during translation", + default=False, cmdline="--lowmem", + requires=[("objspace.geninterp", False)]), + + ]) +def get_pypy_config(overrides=None, translating=False): + from pypy.config.translationoption import get_combined_translation_config + return get_combined_translation_config( + pypy_optiondescription, overrides=overrides, + translating=translating) if __name__ == '__main__': - config = Config(pypy_optiondescription) + config = get_pypy_config() print config.getpaths() parser = to_optparse(config) #, useoptions=["translation.*"]) option, args = parser.parse_args() 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 Mon Dec 4 20:12:22 2006 @@ -1,26 +1,25 @@ import py -from pypy.config.pypyoption import pypy_optiondescription -from pypy.config.config import Config +from pypy.config.pypyoption import get_pypy_config def test_required(): - conf = Config(pypy_optiondescription) + conf = get_pypy_config() assert not conf.translating assert conf.objspace.usemodules.gc conf.objspace.std.withsmallint = True assert not conf.objspace.std.withprebuiltint - conf = Config(pypy_optiondescription) + conf = get_pypy_config() conf.objspace.std.withprebuiltint = True py.test.raises(ValueError, "conf.objspace.std.withsmallint = True") def test_objspace_incopatibilities(): - conf = Config(pypy_optiondescription) + conf = get_pypy_config() conf.objspace.name = "logic" assert not conf.objspace.geninterp def test_stacklessgc_required(): - conf = Config(pypy_optiondescription) + conf = get_pypy_config() conf.translation.gc = "stacklessgc" assert conf.translation.stackless assert conf.translation.type_system == "lltype" Added: pypy/dist/pypy/config/translationoption.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/config/translationoption.py Mon Dec 4 20:12:22 2006 @@ -0,0 +1,145 @@ +import autopath +import py, os +from pypy.config.config import OptionDescription, BoolOption, IntOption, ArbitraryOption +from pypy.config.config import ChoiceOption, StrOption, to_optparse, Config + +translation_optiondescription = OptionDescription( + "translation", "Translation Options", [ + BoolOption("stackless", "compile stackless features in", + default=False, cmdline="--stackless", + requires=[("translation.type_system", "lltype")]), + ChoiceOption("type_system", "Type system to use when RTyping", + ["lltype", "ootype"], cmdline=None), + ChoiceOption("backend", "Backend to use for code generation", + ["c", "llvm", "cli", "js", "squeak", "cl"], + requires={ + "c": [("translation.type_system", "lltype")], + "llvm": [("translation.type_system", "lltype"), + ("translation.gc", "boehm"), + ("translation.backendopt.raisingop2direct_call", True)], + "cli": [("translation.type_system", "ootype")], + "js": [("translation.type_system", "ootype")], + "squeak": [("translation.type_system", "ootype")], + "cl": [("translation.type_system", "ootype")], + }, + cmdline="-b --backend"), + ChoiceOption("gc", "Garbage Collection Strategy", + ["boehm", "ref", "framework", "none", "stacklessgc", + "exact_boehm"], + "boehm", requires={ + "stacklessgc": [("translation.stackless", True)]}, + cmdline="--gc"), + BoolOption("thread", "enable use of threading primitives", + default=False, cmdline="--thread"), + BoolOption("verbose", "Print extra information", default=False), + BoolOption("debug", "Record extra annotation information", + cmdline="-d --debug", default=False), + BoolOption("insist", "Try hard to go on RTyping", default=False, + cmdline="--insist"), + BoolOption("countmallocs", "Count mallocs and frees", default=False, + cmdline=None), + + # misc + StrOption("cc", "Specify compiler", cmdline="--cc"), + StrOption("profopt", "Specify profile based optimization script", + cmdline="--profopt"), + BoolOption("debug_transform", "Perform the debug transformation", + default=False, cmdline="--debug-transform", negation=False), + + BoolOption("instrument", "internal: turn instrumentation on", + default=False, cmdline=None), + + ArbitraryOption("instrumentctl", "internal", + default=None), + + # portability options + BoolOption("vanilla", + "Try to be as portable as possible, which is not much", + default=False, + cmdline="--vanilla", + requires=[("translation.no__thread", True)]), + BoolOption("no__thread", + "don't use __thread for implementing TLS", + default=False, cmdline="--no__thread", negation=False), + StrOption("compilerflags", "Specify flags for the compiler", + cmdline="--cflags"), + StrOption("linkerflags", "Specify flags for the linker", + cmdline="--ldflags"), + + # Flags of the TranslationContext: + BoolOption("simplifying", "Simplify flow graphs", default=True), + BoolOption("do_imports_immediately", "XXX", default=True, + cmdline=None), + BoolOption("builtins_can_raise_exceptions", "XXX", default=False, + cmdline=None), + BoolOption("list_comprehension_operations", "XXX", default=False, + cmdline=None), + ChoiceOption("fork_before", + "(UNIX) Create restartable checkpoint before step", + ["annotate", "rtype", "backendopt", "database", "source"], + default=None, cmdline="--fork-before"), + + OptionDescription("backendopt", "Backend Optimization Options", [ + BoolOption("print_statistics", "Print statistics while optimizing", + default=False), + BoolOption("merge_if_blocks", "Merge if ... elif chains", + cmdline="--if-block-merge", default=True), + BoolOption("raisingop2direct_call", + "Transform exception raising operations", + default=False, cmdline="--raisingop2direct_call"), + BoolOption("mallocs", "Remove mallocs", default=True), + BoolOption("constfold", "Constant propagation", + default=True), + BoolOption("heap2stack", "Escape analysis and stack allocation", + default=False, + requires=[("translation.stackless", False)]), + BoolOption("clever_malloc_removal", + "Remove mallocs in a clever way", default=False), + BoolOption("remove_asserts", + "Kill 'raise AssertionError', which lets the C " + "optimizer remove the asserts", default=False), + IntOption("inline_threshold", "Threshold when to inline functions", + default=1, cmdline=None), + StrOption("profile_based_inline", + "Use call count profiling to drive inlining" + ", specify arguments", + default=None, cmdline="--prof-based-inline"), + ]), + + OptionDescription("cli", "GenCLI options", [ + BoolOption("trace_calls", "Trace function calls", default=False, + cmdline="--cli-trace-calls") + ]), +]) + +def get_combined_translation_config(other_optdescr=None, + existing_config=None, + overrides=None, + translating=False): + if overrides is None: + overrides = {} + d = BoolOption("translating", + "indicates whether we are translating currently", + default=False, cmdline=None) + if other_optdescr is None: + children = [] + newname = "" + else: + children = [other_optdescr] + newname = other_optdescr._name + if existing_config is None: + children += [d, translation_optiondescription] + else: + children += [child for child in existing_config._cfgimpl_descr._children + if child._name != newname] + descr = OptionDescription("pypy", "all options", children) + config = Config(descr, **overrides) + if translating: + config.translating = True + if existing_config is not None: + for child in existing_config._cfgimpl_descr._children: + if child._name == newname: + continue + value = getattr(existing_config, child._name) + config._cfgimpl_values[child._name] = value + return config Modified: pypy/dist/pypy/interpreter/baseobjspace.py ============================================================================== --- pypy/dist/pypy/interpreter/baseobjspace.py (original) +++ pypy/dist/pypy/interpreter/baseobjspace.py Mon Dec 4 20:12:22 2006 @@ -170,16 +170,15 @@ # set recursion limit # sets all the internal descriptors if config is None: - from pypy.config.config import Config - from pypy.config.pypyoption import pypy_optiondescription - config = Config(pypy_optiondescription) + from pypy.config.pypyoption import get_pypy_config + config = get_pypy_config(translating=True) self.config = config self.interned_strings = {} self.pending_actions = [] self.setoptions(**kw) - if self.config.objspace.logbytecodes: - self.bytecodecounts = {} +# if self.config.objspace.logbytecodes: +# self.bytecodecounts = {} self.initialize() Modified: pypy/dist/pypy/tool/build/config.py ============================================================================== --- pypy/dist/pypy/tool/build/config.py (original) +++ pypy/dist/pypy/tool/build/config.py Mon Dec 4 20:12:22 2006 @@ -18,8 +18,8 @@ # compile option config, used by client to parse info, by startcompile for # cmdline args, defaults are taken from the optiondescription -from pypy.config.pypyoption import pypy_optiondescription -compile_config = Config(pypy_optiondescription) +from pypy.config.pypyoption import get_pypy_config +compile_config = get_pypy_config() compile_config.override({'translation.backend': 'c'}) # settings for the server Modified: pypy/dist/pypy/tool/option.py ============================================================================== --- pypy/dist/pypy/tool/option.py (original) +++ pypy/dist/pypy/tool/option.py Mon Dec 4 20:12:22 2006 @@ -2,7 +2,7 @@ # XXX needs clean-up and reorganization. import os -from pypy.config.pypyoption import pypy_optiondescription +from pypy.config.pypyoption import get_pypy_config from pypy.config.config import Config, OptionDescription, to_optparse from py.compat import optparse make_option = optparse.make_option @@ -24,7 +24,7 @@ def get_standard_options(): - config = Config(pypy_optiondescription) + config = get_pypy_config() parser = to_optparse(config, useoptions=["objspace.*"]) parser.add_option( '-H', action="callback", @@ -54,9 +54,7 @@ # XXX this whole file should sooner or later go away and the cmd line # options be generated from the option description. it's especially messy # since we have to check whether the default was actually overwritten - from pypy.config.pypyoption import pypy_optiondescription - from pypy.config.config import Config - conf = Config(pypy_optiondescription) + conf = get_pypy_config() if kwds.get("objspace", None) is not None: conf.objspace.name = kwds["objspace"] if getattr(cmdlineopt, "objspace", None) is not None: Modified: pypy/dist/pypy/translator/c/genc.py ============================================================================== --- pypy/dist/pypy/translator/c/genc.py (original) +++ pypy/dist/pypy/translator/c/genc.py Mon Dec 4 20:12:22 2006 @@ -29,9 +29,8 @@ self.originalentrypoint = entrypoint self.gcpolicy = gcpolicy if config is None: - from pypy.config.config import Config - from pypy.config.pypyoption import pypy_optiondescription - config = Config(pypy_optiondescription) + from pypy.config.pypyoption import get_pypy_config + config = get_pypy_config(translating=True) if gcpolicy is not None and gcpolicy.requires_stackless: config.translation.stackless = True self.config = config Modified: pypy/dist/pypy/translator/c/test/test_boehm.py ============================================================================== --- pypy/dist/pypy/translator/c/test/test_boehm.py (original) +++ pypy/dist/pypy/translator/c/test/test_boehm.py Mon Dec 4 20:12:22 2006 @@ -3,8 +3,6 @@ from pypy.translator.tool.cbuild import check_boehm_presence from pypy.translator.c.genc import CExtModuleBuilder from pypy import conftest -from pypy.config.config import Config -from pypy.config.pypyoption import pypy_optiondescription def setup_module(mod): if not check_boehm_presence(): @@ -23,7 +21,8 @@ def getcompiled(self, func, argstypelist = [], annotatorpolicy=None): - config = Config(pypy_optiondescription) + from pypy.config.pypyoption import get_pypy_config + config = get_pypy_config(translating=True) config.translation.gc = self.gcpolicy config.translation.simplifying = True t = TranslationContext(config=config) Modified: pypy/dist/pypy/translator/c/test/test_newgc.py ============================================================================== --- pypy/dist/pypy/translator/c/test/test_newgc.py (original) +++ pypy/dist/pypy/translator/c/test/test_newgc.py Mon Dec 4 20:12:22 2006 @@ -9,12 +9,11 @@ from pypy.rpython.lltypesystem import lltype, llmemory from pypy.rpython.lltypesystem.lloperation import llop from pypy.rlib.objectmodel import cast_weakgcaddress_to_object, cast_object_to_weakgcaddress -from pypy.config.config import Config -from pypy.config.pypyoption import pypy_optiondescription from pypy import conftest def compile_func(fn, inputtypes, t=None, gcpolicy="ref"): - config = Config(pypy_optiondescription) + from pypy.config.pypyoption import get_pypy_config + config = get_pypy_config(translating=True) config.translation.gc = gcpolicy if t is None: t = TranslationContext(config=config) Modified: pypy/dist/pypy/translator/c/test/test_stackless.py ============================================================================== --- pypy/dist/pypy/translator/c/test/test_stackless.py (original) +++ pypy/dist/pypy/translator/c/test/test_stackless.py Mon Dec 4 20:12:22 2006 @@ -6,7 +6,6 @@ from pypy.rlib.rstack import stack_unwind, stack_frames_depth, stack_too_big from pypy.rlib.rstack import yield_current_frame_to_caller from pypy.config.config import Config -from pypy.config.pypyoption import pypy_optiondescription import os @@ -33,7 +32,8 @@ os.write(1, str(fn())+"\n") return 0 - config = Config(pypy_optiondescription) + from pypy.config.pypyoption import get_pypy_config + config = get_pypy_config(translating=True) config.translation.gc = self.gcpolicy config.translation.stackless = True t = TranslationContext(config=config) Modified: pypy/dist/pypy/translator/c/test/test_typed.py ============================================================================== --- pypy/dist/pypy/translator/c/test/test_typed.py (original) +++ pypy/dist/pypy/translator/c/test/test_typed.py Mon Dec 4 20:12:22 2006 @@ -8,8 +8,6 @@ from pypy.translator.test import snippet from pypy.translator.translator import TranslationContext from pypy.rlib.rarithmetic import r_uint, r_ulonglong, r_longlong, intmask -from pypy.config.config import Config -from pypy.config.pypyoption import pypy_optiondescription # XXX this tries to make compiling faster for full-scale testing from pypy.translator.tool import cbuild @@ -19,7 +17,8 @@ class CompilationTestCase: def annotatefunc(self, func, argtypes=None): - config = Config(pypy_optiondescription) + from pypy.config.pypyoption import get_pypy_config + config = get_pypy_config(translating=True) config.translation.gc = "ref" config.translation.simplifying = True t = TranslationContext(config=config) Modified: pypy/dist/pypy/translator/cli/gencli.py ============================================================================== --- pypy/dist/pypy/translator/cli/gencli.py (original) +++ pypy/dist/pypy/translator/cli/gencli.py Mon Dec 4 20:12:22 2006 @@ -4,7 +4,6 @@ import py from py.compat import subprocess from pypy.config.config import Config -from pypy.config.pypyoption import pypy_optiondescription from pypy.translator.oosupport.genoo import GenOO from pypy.translator.cli import conftest from pypy.translator.cli.ilgenerator import IlasmGenerator Modified: pypy/dist/pypy/translator/driver.py ============================================================================== --- pypy/dist/pypy/translator/driver.py (original) +++ pypy/dist/pypy/translator/driver.py Mon Dec 4 20:12:22 2006 @@ -87,10 +87,8 @@ self.log = log if config is None: - from pypy.config.config import Config - from pypy.config.pypyoption import pypy_optiondescription - config = Config(pypy_optiondescription, - **DEFAULTS) + from pypy.config.pypyoption import get_pypy_config + config = get_pypy_config(DEFAULTS, translating=True) self.config = config if overrides is not None: self.config.override(overrides) Modified: pypy/dist/pypy/translator/goal/targetpypystandalone.py ============================================================================== --- pypy/dist/pypy/translator/goal/targetpypystandalone.py (original) +++ pypy/dist/pypy/translator/goal/targetpypystandalone.py Mon Dec 4 20:12:22 2006 @@ -13,7 +13,6 @@ from pypy.interpreter import gateway from pypy.interpreter.error import OperationError from pypy.translator.goal.ann_override import PyPyAnnotatorPolicy -from pypy.config.pypyoption import pypy_optiondescription from pypy.config.config import Config, to_optparse, make_dict, SUPPRESS_USAGE from pypy.tool.option import make_objspace @@ -94,6 +93,10 @@ def print_help(self, config): self.opt_parser(config).print_help() + def get_additional_config_options(self): + from pypy.config.pypyoption import pypy_optiondescription + return pypy_optiondescription + def target(self, driver, args): driver.exe_name = 'pypy-%(backend)s' @@ -150,7 +153,8 @@ return entry_point, None, PyPyAnnotatorPolicy(single_space = space) def interface(self, ns): - for name in ['take_options', 'handle_config', 'print_help', 'target']: + for name in ['take_options', 'handle_config', 'print_help', 'target', + 'get_additional_config_options']: ns[name] = getattr(self, name) Modified: pypy/dist/pypy/translator/goal/translate.py ============================================================================== --- pypy/dist/pypy/translator/goal/translate.py (original) +++ pypy/dist/pypy/translator/goal/translate.py Mon Dec 4 20:12:22 2006 @@ -11,7 +11,7 @@ from pypy.config.config import to_optparse, OptionDescription, BoolOption, \ ArbitraryOption, StrOption, IntOption, Config, \ ChoiceOption, OptHelpFormatter -from pypy.config.pypyoption import pypy_optiondescription +from pypy.config.translationoption import get_combined_translation_config GOALS= [ @@ -106,8 +106,8 @@ opt_parser.disable_interspersed_args() - config = Config(pypy_optiondescription, - **OVERRIDES) + config = get_combined_translation_config( + overrides=OVERRIDES, translating=True) to_optparse(config, parser=opt_parser, useoptions=['translation.*']) translateconfig = Config(translate_optiondescr) to_optparse(translateconfig, parser=opt_parser) @@ -149,6 +149,14 @@ # based on the config if 'handle_config' in targetspec_dic: targetspec_dic['handle_config'](config) + # give the target the possibility to get its own configuration options + # into the config + if 'get_additional_config_options' in targetspec_dic: + optiondescr = targetspec_dic['get_additional_config_options']() + config = get_combined_translation_config( + optiondescr, + existing_config=config, + translating=True) if translateconfig.help: opt_parser.print_help() Modified: pypy/dist/pypy/translator/interactive.py ============================================================================== --- pypy/dist/pypy/translator/interactive.py (original) +++ pypy/dist/pypy/translator/interactive.py Mon Dec 4 20:12:22 2006 @@ -3,8 +3,6 @@ import autopath from pypy.translator.translator import TranslationContext from pypy.translator import driver -from pypy.config.config import Config -from pypy.config.pypyoption import pypy_optiondescription DEFAULTS = { 'translation.backend': None, Modified: pypy/dist/pypy/translator/js/main.py ============================================================================== --- pypy/dist/pypy/translator/js/main.py (original) +++ pypy/dist/pypy/translator/js/main.py Mon Dec 4 20:12:22 2006 @@ -127,9 +127,8 @@ # XXX: Really do that #options = optparse.Values(defaults=DEFAULT_OPTIONS) #options.debug_transform = opts.debug_transform - from pypy.config.config import Config - from pypy.config.pypyoption import pypy_optiondescription - config = Config(pypy_optiondescription) + from pypy.config.pypyoption import get_pypy_config + config = get_pypy_config(translating=True) config.translation.debug_transform = opts.debug_transform driver = TranslationDriver(config=config) try: Modified: pypy/dist/pypy/translator/llvm/genllvm.py ============================================================================== --- pypy/dist/pypy/translator/llvm/genllvm.py (original) +++ pypy/dist/pypy/translator/llvm/genllvm.py Mon Dec 4 20:12:22 2006 @@ -40,9 +40,8 @@ self.translator = translator if config is None: - from pypy.config.config import Config - from pypy.config.pypyoption import pypy_optiondescription - config = Config(pypy_optiondescription) + from pypy.config.pypyoption import get_pypy_config + config = get_pypy_config(translating=True) self.config = config self.stackless = stackless Modified: pypy/dist/pypy/translator/oosupport/genoo.py ============================================================================== --- pypy/dist/pypy/translator/oosupport/genoo.py (original) +++ pypy/dist/pypy/translator/oosupport/genoo.py Mon Dec 4 20:12:22 2006 @@ -1,7 +1,5 @@ """ basic oogenerator """ -from pypy.config.config import Config -from pypy.config.pypyoption import pypy_optiondescription from pypy.translator.oosupport import constant as ooconst class GenOO(object): @@ -30,7 +28,8 @@ self.entrypoint = entrypoint self.db = self.Database(self) if config is None: - config = Config(pypy_optiondescription) + from pypy.config.pypyoption import get_pypy_config + config = get_pypy_config(translating=True) self.config = config def generate_source(self): Modified: pypy/dist/pypy/translator/test/test_driver.py ============================================================================== --- pypy/dist/pypy/translator/test/test_driver.py (original) +++ pypy/dist/pypy/translator/test/test_driver.py Mon Dec 4 20:12:22 2006 @@ -1,8 +1,6 @@ import py from pypy.translator.driver import TranslationDriver -from pypy.config.config import Config -from pypy.config.pypyoption import pypy_optiondescription from py.compat import optparse def cmpl(l1, l2): Modified: pypy/dist/pypy/translator/translator.py ============================================================================== --- pypy/dist/pypy/translator/translator.py (original) +++ pypy/dist/pypy/translator/translator.py Mon Dec 4 20:12:22 2006 @@ -11,6 +11,8 @@ from pypy.objspace.flow import FlowObjSpace from pypy.tool.ansi_print import ansi_log from pypy.tool.sourcetools import nice_repr_for_func +from pypy.config.pypyoption import pypy_optiondescription +from pypy.config.translationoption import get_combined_translation_config import py log = py.log.Producer("flowgraph") py.log.setconsumer("flowgraph", ansi_log) @@ -26,9 +28,8 @@ def __init__(self, config=None, **flowing_flags): if config is None: - from pypy.config.config import Config - from pypy.config.pypyoption import pypy_optiondescription - config = Config(pypy_optiondescription) + from pypy.config.pypyoption import get_pypy_config + config = get_pypy_config(translating=True) # ZZZ should go away in the end for attr in ['verbose', 'simplifying', 'do_imports_immediately', 'builtins_can_raise_exceptions', @@ -36,6 +37,7 @@ if attr in flowing_flags: setattr(config.translation, attr, flowing_flags[attr]) self.config = config + self.create_flowspace_config() self.annotator = None self.rtyper = None self.exceptiontransformer = None @@ -45,6 +47,17 @@ self._implicitly_called_by_externals = [] + def create_flowspace_config(self): + # XXX this is a hack: we create a new config, which is only used + # for the flow object space. The problem is that the flow obj space + # needs an objspace config, but the thing we are translating might not + # have one (or worse we are translating pypy and the flow space picks + # up strange options of the pypy we are translating). Therefore we need + # to construct this new config + self.flowconfig = get_combined_translation_config( + pypy_optiondescription, self.config, translating=True) + self.flowconfig.objspace.name = "flow" + def buildflowgraph(self, func): """Get the flow graph for a function.""" if not isinstance(func, types.FunctionType): @@ -55,7 +68,7 @@ else: if self.config.translation.verbose: log.start(nice_repr_for_func(func)) - space = FlowObjSpace(self.config) + space = FlowObjSpace(self.flowconfig) if self.annotator: # ZZZ self.annotator.policy._adjust_space_config(space) From cfbolz at codespeak.net Mon Dec 4 20:52:26 2006 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Mon, 4 Dec 2006 20:52:26 +0100 (CET) Subject: [pypy-svn] r35267 - pypy/dist/pypy/translator/c Message-ID: <20061204195226.903761007C@code0.codespeak.net> Author: cfbolz Date: Mon Dec 4 20:52:24 2006 New Revision: 35267 Modified: pypy/dist/pypy/translator/c/genc.py Log: make this config argument non-optional Modified: pypy/dist/pypy/translator/c/genc.py ============================================================================== --- pypy/dist/pypy/translator/c/genc.py (original) +++ pypy/dist/pypy/translator/c/genc.py Mon Dec 4 20:52:24 2006 @@ -22,15 +22,12 @@ symboltable = None modulename = None - def __init__(self, translator, entrypoint, config=None, libraries=None, + def __init__(self, translator, entrypoint, config, libraries=None, gcpolicy=None): self.translator = translator self.entrypoint = entrypoint self.originalentrypoint = entrypoint self.gcpolicy = gcpolicy - if config is None: - from pypy.config.pypyoption import get_pypy_config - config = get_pypy_config(translating=True) if gcpolicy is not None and gcpolicy.requires_stackless: config.translation.stackless = True self.config = config From ericvrp at codespeak.net Mon Dec 4 22:08:55 2006 From: ericvrp at codespeak.net (ericvrp at codespeak.net) Date: Mon, 4 Dec 2006 22:08:55 +0100 (CET) Subject: [pypy-svn] r35272 - pypy/dist/pypy/jit/codegen/llvm Message-ID: <20061204210855.01AA610077@code0.codespeak.net> Author: ericvrp Date: Mon Dec 4 22:08:46 2006 New Revision: 35272 Modified: pypy/dist/pypy/jit/codegen/llvm/rgenop.py Log: Added some debug prints. Slowly working towards first passing test. Modified: pypy/dist/pypy/jit/codegen/llvm/rgenop.py ============================================================================== --- pypy/dist/pypy/jit/codegen/llvm/rgenop.py (original) +++ pypy/dist/pypy/jit/codegen/llvm/rgenop.py Mon Dec 4 22:08:46 2006 @@ -1,8 +1,14 @@ from pypy.rlib.objectmodel import specialize +from pypy.rpython.lltypesystem import lltype, llmemory from pypy.jit.codegen.model import AbstractRGenOp, GenLabel, GenBuilder from pypy.jit.codegen.model import GenVar, GenConst, CodeGenSwitch +def log(s): + print str(s) + pass + + class Var(GenVar): def __init__(self): @@ -14,7 +20,7 @@ class IntConst(GenConst): def __init__(self, value): - self.value = value + self.value = value @specialize.arg(1) def revealconst(self, T): @@ -60,16 +66,19 @@ # def __init__(self, rgenop): + log('FlexSwitch.__init__') self.rgenop = rgenop self.default_case_addr = 0 def initialize(self, builder, gv_exitswitch): + log('FlexSwitch.initialize') mc = builder.mc mc.MOV(eax, gv_exitswitch.operand(builder)) self.saved_state = builder._save_state() self._reserve(mc) def _reserve(self, mc): + log('FlexSwitch._reserve') RESERVED = 11*4+5 # XXX quite a lot for now :-/ pos = mc.tell() mc.UD2() @@ -78,6 +87,7 @@ self.endfreepos = pos + RESERVED def _reserve_more(self): + log('FlexSwitch._reserve_more') start = self.nextfreepos end = self.endfreepos newmc = self.rgenop.open_mc() @@ -88,6 +98,7 @@ fullmc.done() def add_case(self, gv_case): + log('FlexSwitch.add_case') rgenop = self.rgenop targetbuilder = Builder._new_from_state(rgenop, self.saved_state) target_addr = targetbuilder.mc.tell() @@ -99,6 +110,7 @@ return targetbuilder def _add_case(self, gv_case, target_addr): + log('FlexSwitch._add_case') start = self.nextfreepos end = self.endfreepos mc = InMemoryCodeBuilder(start, end) @@ -118,6 +130,7 @@ self.nextfreepos = pos def add_default(self): + log('FlexSwitch.add_default') rgenop = self.rgenop targetbuilder = Builder._new_from_state(rgenop, self.saved_state) self.default_case_addr = targetbuilder.mc.tell() @@ -131,30 +144,100 @@ # -class Builder(GenBuilder): +class Builder(object): #changed baseclass from (GenBuilder) for better error messages def __init__(self, rgenop): + log('Builder.__init__') self.rgenop = rgenop + self.asm = [] #list of llvm assembly source code lines # ---------------------------------------------------------------- # The public Builder interface def end(self): + log('Builder.end') pass + def _write_prologue(self, sigtoken): + log('Builder._write_prologue') + numargs = sigtoken # for now + #self.mc.BREAKPOINT() + return [Var() for i in range(numargs)] + + def _close(self): + log('Builder._close') + return + self.mc.done() + self.rgenop.close_mc(self.mc) + self.mc = None + @specialize.arg(1) def genop1(self, opname, gv_arg): + log('Builder.genop1') genmethod = getattr(self, 'op_' + opname) return genmethod(gv_arg) @specialize.arg(1) def genop2(self, opname, gv_arg1, gv_arg2): + log('Builder.genop2') genmethod = getattr(self, 'op_' + opname) return genmethod(gv_arg1, gv_arg2) + def op_int_add(self, gv_x, gv_y): + log('Builder.op_int_add') + gv_result = Var() + return gv_result + self.mc.MOV(eax, gv_x.operand(self)) + self.mc.ADD(eax, gv_y.operand(self)) + return self.returnvar(eax) + + def enter_next_block(self, kinds, args_gv): + log('Builder.enter_next_block') + return + arg_positions = [] + seen = {} + for i in range(len(args_gv)): + gv = args_gv[i] + # turn constants into variables; also make copies of vars that + # are duplicate in args_gv + if not isinstance(gv, Var) or gv.stackpos in seen: + gv = args_gv[i] = self.returnvar(gv.operand(self)) + # remember the var's position in the stack + arg_positions.append(gv.stackpos) + seen[gv.stackpos] = None + return Label(self.mc.tell(), arg_positions, self.stackdepth) + + def finish_and_return(self, sigtoken, gv_returnvar): + log('Builder.finish_and_return') + return + numargs = sigtoken # for now + initialstackdepth = numargs + 1 + self.mc.MOV(eax, gv_returnvar.operand(self)) + self.mc.ADD(esp, imm(WORD * (self.stackdepth - initialstackdepth))) + self.mc.RET() + self._close() + + def finish_and_goto(self, outputargs_gv, target): + log('Builder.finish_and_goto') + return + remap_stack_layout(self, outputargs_gv, target) + self.mc.JMP(rel32(target.startaddr)) + self._close() + + def flexswitch(self, gv_exitswitch): + log('Builder.flexswitch') + return + result = FlexSwitch(self.rgenop) + result.initialize(self, gv_exitswitch) + self._close() + return result + + def show_incremental_progress(self): + log('Builder.show_incremental_progress') + pass -class RLLVMGenOp(AbstractRGenOp): +class RLLVMGenOp(object): #changed baseclass from (AbstractRGenOp) for better error messages def __init__(self): #self.mcs = [] # machine code blocks where no-one is currently writing @@ -165,12 +248,15 @@ # the public RGenOp interface def openbuilder(self): + log('RLLVMGenOp.openbuilder') return Builder(self) def newgraph(self, sigtoken, name): + log('RLLVMGenOp.newgraph') numargs = sigtoken # for now builder = self.openbuilder() - entrypoint = builder.asm.mc.tell() + #entrypoint = builder.asm.mc.tell() + entrypoint = 0 #XXX inputargs_gv = builder._write_prologue(sigtoken) return builder, IntConst(entrypoint), inputargs_gv @@ -248,3 +334,4 @@ global_rgenop = RLLVMGenOp() RLLVMGenOp.constPrebuiltGlobal = global_rgenop.genconst + From pedronis at codespeak.net Mon Dec 4 22:48:58 2006 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Mon, 4 Dec 2006 22:48:58 +0100 (CET) Subject: [pypy-svn] r35276 - pypy/branch/jit-real-world/pypy/jit/timeshifter/test Message-ID: <20061204214858.CEC5A1007A@code0.codespeak.net> Author: pedronis Date: Mon Dec 4 22:48:57 2006 New Revision: 35276 Modified: pypy/branch/jit-real-world/pypy/jit/timeshifter/test/test_timeshift.py Log: (arre, pedronis) work in progress test about green call site for red returning graphs. Modified: pypy/branch/jit-real-world/pypy/jit/timeshifter/test/test_timeshift.py ============================================================================== --- pypy/branch/jit-real-world/pypy/jit/timeshifter/test/test_timeshift.py (original) +++ pypy/branch/jit-real-world/pypy/jit/timeshifter/test/test_timeshift.py Mon Dec 4 22:48:57 2006 @@ -1132,3 +1132,17 @@ res = self.timeshift(f, [4, 5], [0, 1], policy=P_NOVIRTUAL) assert res == 42 self.check_insns({}) + + def test_green_red_mismatch_in_call(self): + py.test.skip("WIP") + def add(a,b, u): + return a+b + + def f(x, y, u): + r = add(x+1,y+1, u) + z = x+y + hint(z, concrete=True) + return hint(z, variable=True) + + res = self.timeshift(f, [4, 5, 0], [], policy=P_NOVIRTUAL) + assert res == 9 From arigo at codespeak.net Tue Dec 5 02:02:01 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 5 Dec 2006 02:02:01 +0100 (CET) Subject: [pypy-svn] r35278 - in pypy/branch/jit-real-world/pypy/jit: hintannotator hintannotator/test timeshifter timeshifter/test Message-ID: <20061205010201.DE6AA10068@code0.codespeak.net> Author: arigo Date: Tue Dec 5 02:01:56 2006 New Revision: 35278 Modified: pypy/branch/jit-real-world/pypy/jit/hintannotator/annotator.py pypy/branch/jit-real-world/pypy/jit/hintannotator/bookkeeper.py pypy/branch/jit-real-world/pypy/jit/hintannotator/model.py pypy/branch/jit-real-world/pypy/jit/hintannotator/test/test_annotator.py pypy/branch/jit-real-world/pypy/jit/timeshifter/hrtyper.py pypy/branch/jit-real-world/pypy/jit/timeshifter/test/test_timeshift.py Log: (pedronis, arre on the earlier sweat part, arigo) Don't use the RPython's normalization in the hint-annotator. It took quite some sweat to discover that it was not a good idea. Instead, for all the variables whose color is not fixed at the end of hint-annotation, we proceed by assuming that they are all green and forcing them to red as needed, in a fixpoint process again. The "needs" is based on the dependencies captured by 'myorigin' and by the call families, which produces the normalization effect. Modified: pypy/branch/jit-real-world/pypy/jit/hintannotator/annotator.py ============================================================================== --- pypy/branch/jit-real-world/pypy/jit/hintannotator/annotator.py (original) +++ pypy/branch/jit-real-world/pypy/jit/hintannotator/annotator.py Tue Dec 5 02:01:56 2006 @@ -10,9 +10,12 @@ class HintAnnotatorPolicy(policy.AnnotatorPolicy): - def __init__(self, novirtualcontainer=False, oopspec=False): - self.novirtualcontainer = novirtualcontainer - self.oopspec = oopspec + def __init__(self, novirtualcontainer = False, + oopspec = False, + entrypoint_returns_red = True): + self.novirtualcontainer = novirtualcontainer + self.oopspec = oopspec + self.entrypoint_returns_red = entrypoint_returns_red def look_inside_graph(self, graph): return True Modified: pypy/branch/jit-real-world/pypy/jit/hintannotator/bookkeeper.py ============================================================================== --- pypy/branch/jit-real-world/pypy/jit/hintannotator/bookkeeper.py (original) +++ pypy/branch/jit-real-world/pypy/jit/hintannotator/bookkeeper.py Tue Dec 5 02:01:56 2006 @@ -25,12 +25,15 @@ # modify input_args_hs in-place to change their origin for i in range(len(input_args_hs)): - old = self.bookkeeper.enter((graph, i)) - try: - input_args_hs[i] = hintmodel.reorigin(input_args_hs[i]) - finally: - self.bookkeeper.leave(old) - + hs_v1 = input_args_hs[i] + if isinstance(hs_v1, hintmodel.SomeLLAbstractConstant): + myorigin = self.bookkeeper.myinputargorigin(graph, i) + hs_v1 = hintmodel.SomeLLAbstractConstant( + hs_v1.concretetype, {myorigin: True}, + eager_concrete = hs_v1.eager_concrete, + deepfrozen = hs_v1.deepfrozen, + myorigin = myorigin) + input_args_hs[i] = hs_v1 return graph def cachedgraph(self, key, alt_name=None): @@ -100,31 +103,80 @@ else: self.position_key = old + def myinputargorigin(self, graph, i): + try: + origin = self.originflags[graph, i] + except KeyError: + origin = hintmodel.InputArgOriginFlags(self, graph, i) + self.originflags[graph, i] = origin + return origin + def myorigin(self): try: origin = self.originflags[self.position_key] except KeyError: - if len(self.position_key) == 3: - graph, block, i = self.position_key - spaceop = block.operations[i] - spaceop = SpaceOperation(spaceop.opname, - list(spaceop.args), - spaceop.result) - else: - spaceop = None + assert len(self.position_key) == 3 + graph, block, i = self.position_key + spaceop = block.operations[i] + spaceop = SpaceOperation(spaceop.opname, + list(spaceop.args), + spaceop.result) origin = hintmodel.OriginFlags(self, spaceop) self.originflags[self.position_key] = origin return origin def compute_at_fixpoint(self): - pass + binding = self.annotator.binding - def compute_after_normalization(self): - # compute and cache the green-ness of OriginFlags objects - # while we can do so (i.e. before the graphs are modified). + # for the entry point, we need to remove the 'myorigin' of + # the input arguments (otherwise they will always be green, + # as there is no call to the entry point to make them red) + tsgraph = self.annotator.translator.graphs[0] + for v in tsgraph.getargs(): + hs_arg = binding(v) + if isinstance(hs_arg, hintmodel.SomeLLAbstractConstant): + hs_arg.myorigin = None + # for convenience, force the return var to be red too, as + # the timeshifter doesn't support anything else + if self.annotator.policy.entrypoint_returns_red: + v = tsgraph.getreturnvar() + hs_red = hintmodel.variableoftype(v.concretetype) + self.annotator.setbinding(v, hs_red) + + # propagate the green/red constraints + log.event("Computing maximal green set...") + greenorigindependencies = {} for origin in self.originflags.values(): - if origin.spaceop is not None: - origin.greenargs_cached = origin.greenargs() + origin.greenargs = True + origin.record_dependencies(greenorigindependencies) + + while True: + progress = False + for origin, deps in greenorigindependencies.items(): + for v in deps: + if not binding(v).is_green(): + # not green => force the origin to be red too + origin.greenargs = False + del greenorigindependencies[origin] + progress = True + break + if not progress: + break + + for callfamily in self.tsgraph_maximal_call_families.infos(): + if len(callfamily.tsgraphs) > 1: + # if at least one graph in the family returns a red, + # we force a red as the return of all of them + returns_red = False + for graph in callfamily.tsgraphs: + if not binding(graph.getreturnvar()).is_green(): + returns_red = True + if returns_red: + for graph in callfamily.tsgraphs: + v = graph.getreturnvar() + hs_red = hintmodel.variableoftype(v.concretetype) + self.annotator.setbinding(v, hs_red) + # compute and cache the signature of the graphs before they are # modified by further code ha = self.annotator @@ -249,8 +301,12 @@ hs_res = hintmodel.reorigin(hs_res, *deps_hs) return hs_res - def graph_family_call(self, graph_list, fixed, args_hs): - tsgraphs = [] + def graph_family_call(self, graph_list, fixed, args_hs, + tsgraphs_accum=None): + if tsgraphs_accum is None: + tsgraphs = [] + else: + tsgraphs = tsgraphs_accum results_hs = [] for graph in graph_list: results_hs.append(self.graph_call(graph, fixed, args_hs, tsgraphs)) Modified: pypy/branch/jit-real-world/pypy/jit/hintannotator/model.py ============================================================================== --- pypy/branch/jit-real-world/pypy/jit/hintannotator/model.py (original) +++ pypy/branch/jit-real-world/pypy/jit/hintannotator/model.py Tue Dec 5 02:01:56 2006 @@ -33,22 +33,26 @@ pass class OriginFlags(object): - fixed = False read_positions = None - greenargs_cached = None - is_call_result = False + greenargs = False def __init__(self, bookkeeper=None, spaceop=None): self.bookkeeper = bookkeeper self.spaceop = spaceop def __repr__(self): + return '<%s %s>' % (getattr(self.spaceop, 'result', '?'), + self.reprstate()) + + def reprstate(self): if self.fixed: s = "fixed " + elif self.greenargs: + s = "green" else: s = "" - return "<%sorigin>" % (s,) + return "%sorigin" % (s,) def read_fixed(self): if self.read_positions is None: @@ -64,63 +68,66 @@ for p in self.read_positions: annotator.reflowfromposition(p) - def greenargs(self, frame=None): - annotator = self.bookkeeper.annotator - if frame is None: - if self.greenargs_cached is not None: - return self.greenargs_cached - frame = GreenHandlerFrame(annotator) - if self.is_call_result: - return frame.greencallresult(self.spaceop) + def record_dependencies(self, greenorigindependencies): + deps = greenorigindependencies.setdefault(self, []) + deps.extend(self.spaceop.args) + + +class CallOpOriginFlags(OriginFlags): + + def record_dependencies(self, greenorigindependencies): + bk = self.bookkeeper + if self.spaceop.opname == 'direct_call': + args = self.spaceop.args[1:] + elif self.spaceop.opname == 'indirect_call': + args = self.spaceop.args[1:-1] else: - for v in self.spaceop.args: - if not frame.greenvar(v): - return False - return True - - -class GreenHandlerFrame(object): - - def __init__(self, annotator, parentframe=None): - self.annotator = annotator - self.parentframe = parentframe - self.inputarg2actualarg = {} # {origin: annotation} - - def greenvar(self, v): - hs = self.annotator.binding(v) - if isinstance(hs, SomeLLAbstractConstant) and len(hs.origins) == 1: - [o] = hs.origins.keys() - if o in self.inputarg2actualarg: - hs_actual = self.inputarg2actualarg[o] - return hs_actual.is_green(self.parentframe) - return hs.is_green(self) - - def greencallresult(self, spaceop): -## print spaceop -## if str(spaceop.result) == 'v58': -## import pdb; pdb.set_trace() - args_hs = [self.annotator.binding(v) for v in spaceop.args] - hs_result = self.annotator.binding(spaceop.result) - if not isinstance(hs_result, SomeLLAbstractConstant): - return False # was generalized, e.g. to SomeLLAbstractVariable - hs_f1 = args_hs.pop(0) - fnobj = hs_f1.const._obj - if (self.annotator.policy.oopspec and - hasattr(fnobj._callable, 'oopspec')): - assert False # XXX? + raise AssertionError(self.spaceop.opname) - input_args_hs = list(args_hs) - bk = self.annotator.bookkeeper - graph = bk.get_graph_for_call(fnobj.graph, - hs_result.is_fixed(), - input_args_hs) - newframe = GreenHandlerFrame(self.annotator, parentframe=self) - for hs_inp_arg, hs_arg in zip(input_args_hs, args_hs): - if isinstance(hs_arg, SomeLLAbstractConstant): - assert len(hs_inp_arg.origins) == 1 - [o] = hs_inp_arg.origins.keys() - newframe.inputarg2actualarg[o] = hs_arg - return newframe.greenvar(graph.getreturnvar()) + graph = self.any_called_graph + call_families = bk.tsgraph_maximal_call_families + _, repgraph, callfamily = call_families.find(graph) + + # record the argument and return value dependencies + retdeps = greenorigindependencies.setdefault(self, []) + for graph in callfamily.tsgraphs: + retdeps.append(graph.getreturnvar()) + for i, v in enumerate(args): + argorigin = bk.myinputargorigin(graph, i) + deps = greenorigindependencies.setdefault(argorigin, []) + deps.append(v) + + +class InputArgOriginFlags(OriginFlags): + + def __init__(self, bookkeeper, graph, i): + OriginFlags.__init__(self, bookkeeper) + self.graph = graph + self.i = i + + def getarg(self): + return self.graph.getargs()[self.i] + + def __repr__(self): + return '<%s %s>' % (self.getarg(), self.reprstate()) + + def record_dependencies(self, greenorigindependencies): + bk = self.bookkeeper + call_families = bk.tsgraph_maximal_call_families + _, repgraph, callfamily = call_families.find(self.graph) + + # record the fact that each graph's input args should be as red + # as each other's + if self.graph is repgraph: + deps = greenorigindependencies.setdefault(self, []) + v = self.getarg() + for othergraph in callfamily.tsgraphs: + if othergraph is not repgraph: + deps.append(othergraph.getargs()[self.i]) + otherorigin = bk.myinputargorigin(othergraph, self.i) + otherdeps = greenorigindependencies.setdefault(otherorigin, + []) + otherdeps.append(v) # ____________________________________________________________ @@ -132,7 +139,7 @@ assert self.__class__ != SomeLLAbstractValue self.deepfrozen = deepfrozen - def is_green(self, frame=None): + def is_green(self): return False @@ -145,12 +152,11 @@ self.origins = origins self.eager_concrete = eager_concrete self.myorigin = myorigin - assert myorigin is None or myorigin.spaceop is not None def fmt_origins(self, origins): counts = {} for o in origins: - x = repr(o) + x = o.reprstate() counts[x] = counts.get(x, 0) + 1 items = counts.items() items.sort() @@ -167,7 +173,7 @@ if myorigin is None: return None else: - return str(myorigin.spaceop.result) + return repr(myorigin) def is_fixed(self): for o in self.origins: @@ -175,18 +181,19 @@ return False return True - def is_green(self, frame=None): + def is_green(self): return (self.is_fixed() or self.eager_concrete or self.concretetype is lltype.Void or - (self.myorigin is not None and - self.myorigin.greenargs(frame))) + (self.myorigin is not None and self.myorigin.greenargs)) def annotationcolor(self): """Compute the color of the variables with this annotation for the pygame viewer """ try: - if self.eager_concrete: + if self.concretetype is lltype.Void: + return annmodel.s_ImpossibleValue.annotationcolor + elif self.eager_concrete: return (0,100,0) # green elif self.is_green(): return (50,140,0) # green-dark-cyan @@ -328,11 +335,16 @@ # cannot follow return variableoftype(hs_v1.concretetype.TO.RESULT) - fixed = bookkeeper.myorigin().read_fixed() - hs_res = bookkeeper.graph_family_call(graph_list, fixed, args_hs) + myorigin = bookkeeper.myorigin() + myorigin.__class__ = CallOpOriginFlags # thud + fixed = myorigin.read_fixed() + tsgraphs_accum = [] + hs_res = bookkeeper.graph_family_call(graph_list, fixed, args_hs, + tsgraphs_accum) + myorigin.any_called_graph = tsgraphs_accum[0] if isinstance(hs_res, SomeLLAbstractConstant): - hs_res.myorigin = bookkeeper.myorigin() + hs_res.myorigin = myorigin # we need to make sure that hs_res does not become temporarily less # general as a result of calling another specialized version of the @@ -390,12 +402,17 @@ bookkeeper.annotator.translator.graphs[0]): return variableoftype(lltype.typeOf(fnobj).RESULT) - fixed = bookkeeper.myorigin().read_fixed() - hs_res = bookkeeper.graph_call(fnobj.graph, fixed, args_hs) + myorigin = bookkeeper.myorigin() + myorigin.__class__ = CallOpOriginFlags # thud + fixed = myorigin.read_fixed() + tsgraphs_accum = [] + hs_res = bookkeeper.graph_call(fnobj.graph, fixed, args_hs, + tsgraphs_accum) + myorigin.any_called_graph = tsgraphs_accum[0] if isinstance(hs_res, SomeLLAbstractConstant): - hs_res.myorigin = bookkeeper.myorigin() - hs_res.myorigin.is_call_result = True + hs_res.myorigin = myorigin + ## elif fnobj.graph.name.startswith('ll_stritem'): ## if isinstance(hs_res, SomeLLAbstractVariable): ## print hs_res Modified: pypy/branch/jit-real-world/pypy/jit/hintannotator/test/test_annotator.py ============================================================================== --- pypy/branch/jit-real-world/pypy/jit/hintannotator/test/test_annotator.py (original) +++ pypy/branch/jit-real-world/pypy/jit/hintannotator/test/test_annotator.py Tue Dec 5 02:01:56 2006 @@ -10,12 +10,16 @@ from pypy.translator.backendopt.inline import auto_inlining from pypy import conftest -P_OOPSPEC = HintAnnotatorPolicy(oopspec=True) +P_DEFAULT = HintAnnotatorPolicy(entrypoint_returns_red=False) +P_OOPSPEC = HintAnnotatorPolicy(oopspec=True, + entrypoint_returns_red=False) P_OOPSPEC_NOVIRTUAL = HintAnnotatorPolicy(oopspec=True, - novirtualcontainer=True) -P_NOVIRTUAL = HintAnnotatorPolicy(novirtualcontainer=True) + novirtualcontainer=True, + entrypoint_returns_red=False) +P_NOVIRTUAL = HintAnnotatorPolicy(novirtualcontainer=True, + entrypoint_returns_red=False) -def hannotate(func, argtypes, policy=None, annotator=False, inline=None, +def hannotate(func, argtypes, policy=P_DEFAULT, annotator=False, inline=None, backendoptimize=False): # build the normal ll graphs for ll_function t = TranslationContext() Modified: pypy/branch/jit-real-world/pypy/jit/timeshifter/hrtyper.py ============================================================================== --- pypy/branch/jit-real-world/pypy/jit/timeshifter/hrtyper.py (original) +++ pypy/branch/jit-real-world/pypy/jit/timeshifter/hrtyper.py Tue Dec 5 02:01:56 2006 @@ -152,9 +152,9 @@ """ Driver for running the timeshifter. """ - self.type_system.perform_normalizations(self) +## self.type_system.perform_normalizations(self) bk = self.annotator.bookkeeper - bk.compute_after_normalization() +## bk.compute_after_normalization() entrygraph = self.annotator.translator.graphs[0] self.origportalgraph = origportalgraph if origportalgraph: Modified: pypy/branch/jit-real-world/pypy/jit/timeshifter/test/test_timeshift.py ============================================================================== --- pypy/branch/jit-real-world/pypy/jit/timeshifter/test/test_timeshift.py (original) +++ pypy/branch/jit-real-world/pypy/jit/timeshifter/test/test_timeshift.py Tue Dec 5 02:01:56 2006 @@ -1134,15 +1134,15 @@ self.check_insns({}) def test_green_red_mismatch_in_call(self): - py.test.skip("WIP") + #py.test.skip("WIP") def add(a,b, u): return a+b def f(x, y, u): r = add(x+1,y+1, u) z = x+y - hint(z, concrete=True) + z = hint(z, concrete=True) + r # this checks that 'r' is green return hint(z, variable=True) res = self.timeshift(f, [4, 5, 0], [], policy=P_NOVIRTUAL) - assert res == 9 + assert res == 20 From antocuni at codespeak.net Tue Dec 5 11:18:50 2006 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Tue, 5 Dec 2006 11:18:50 +0100 (CET) Subject: [pypy-svn] r35281 - in pypy/dist/pypy/module/_dotnet: . test Message-ID: <20061205101850.C1FDA1006F@code0.codespeak.net> Author: antocuni Date: Tue Dec 5 11:18:48 2006 New Revision: 35281 Modified: pypy/dist/pypy/module/_dotnet/interp_dotnet.py pypy/dist/pypy/module/_dotnet/test/test_dotnet.py Log: Support for conversion between python and .NET floats. Modified: pypy/dist/pypy/module/_dotnet/interp_dotnet.py ============================================================================== --- pypy/dist/pypy/module/_dotnet/interp_dotnet.py (original) +++ pypy/dist/pypy/module/_dotnet/interp_dotnet.py Tue Dec 5 11:18:48 2006 @@ -3,10 +3,10 @@ from pypy.interpreter.gateway import interp2app from pypy.interpreter.typedef import TypeDef from pypy.rpython.ootypesystem import ootype -from pypy.translator.cli.dotnet import CLR, box, unbox, NativeException, native_exc, new_array, init_array +from pypy.translator.cli.dotnet import CLR, box, unbox, NativeException, native_exc,\ + new_array, init_array, typeof -Type = CLR.System.Type -Object = CLR.System.Object +System = CLR.System TargetInvocationException = NativeException(CLR.System.Reflection.TargetInvocationException) import sys @@ -21,7 +21,8 @@ b_meth = b_type.GetMethod(name) # TODO: overloading! b_args = self.rewrap_args(w_args) try: - b_res = b_meth.Invoke(self.b_obj, b_args) + # for an explanation of the box() call, see the log message for revision 35167 + b_res = box(b_meth.Invoke(self.b_obj, b_args)) except TargetInvocationException, e: b_inner = native_exc(e).get_InnerException() message = str(b_inner.get_Message()) @@ -32,7 +33,7 @@ def rewrap_args(self, w_args): args = self.space.unpackiterable(w_args) - b_res = new_array(Object, len(args)) + b_res = new_array(System.Object, len(args)) for i in range(len(args)): b_res[i] = self.py2cli(args[i]) return b_res @@ -41,20 +42,31 @@ space = self.space if space.is_true(space.isinstance(w_obj, self.space.w_int)): return box(space.int_w(w_obj)) + if space.is_true(space.isinstance(w_obj, self.space.w_float)): + return box(space.float_w(w_obj)) else: typename = space.type(w_obj).getname(space, '?') msg = "Can't convert type %s to .NET" % typename raise OperationError(self.space.w_TypeError, self.space.wrap(msg)) def cli2py(self, b_obj): - intval = unbox(b_obj, ootype.Signed) # TODO: support other types - return self.space.wrap(intval) + b_type = b_obj.GetType() + # TODO: support other types + if b_type == typeof(System.Int32): + intval = unbox(b_obj, ootype.Signed) + return self.space.wrap(intval) + elif b_type == typeof(System.Double): + floatval = unbox(b_obj, ootype.Float) + return self.space.wrap(floatval) + else: + msg = "Can't convert object %s to Python" % str(b_obj.ToString()) + raise OperationError(self.space.w_TypeError, self.space.wrap(msg)) def cli_object_new(space, w_subtype, typename): - b_type = Type.GetType(typename) - b_ctor = b_type.GetConstructor(init_array(Type)) - b_obj = b_ctor.Invoke(init_array(Object)) + b_type = System.Type.GetType(typename) + b_ctor = b_type.GetConstructor(init_array(System.Type)) + b_obj = b_ctor.Invoke(init_array(System.Object)) return space.wrap(W_CliObject(space, b_obj)) cli_object_new.unwrap_spec = [ObjSpace, W_Root, str] Modified: pypy/dist/pypy/module/_dotnet/test/test_dotnet.py ============================================================================== --- pypy/dist/pypy/module/_dotnet/test/test_dotnet.py (original) +++ pypy/dist/pypy/module/_dotnet/test/test_dotnet.py Tue Dec 5 11:18:48 2006 @@ -24,3 +24,10 @@ import _dotnet obj = _dotnet.ArrayList() raises(StandardError, obj.get_Item, 0) + + def test_float_conversion(self): + import _dotnet + obj = _dotnet.ArrayList() + obj.Add(42.0) + item = obj.get_Item(0) + assert isinstance(item, float) From cfbolz at codespeak.net Tue Dec 5 11:53:25 2006 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Tue, 5 Dec 2006 11:53:25 +0100 (CET) Subject: [pypy-svn] r35283 - pypy/dist/pypy/rpython/memory/test Message-ID: <20061205105325.43C4E1006F@code0.codespeak.net> Author: cfbolz Date: Tue Dec 5 11:53:21 2006 New Revision: 35283 Modified: pypy/dist/pypy/rpython/memory/test/test_transformed_gc.py Log: give now non-optional config argument 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 Tue Dec 5 11:53:21 2006 @@ -200,7 +200,8 @@ ARGS = lltype.FixedSizeArray(lltype.Signed, nbargs) s_args = annmodel.SomePtr(lltype.Ptr(ARGS)) t = rtype(entrypoint, [s_args], gcname=self.gcname) - cbuild = CStandaloneBuilder(t, entrypoint, gcpolicy=self.gcpolicy) + cbuild = CStandaloneBuilder(t, entrypoint, config=t.config, + gcpolicy=self.gcpolicy) db = cbuild.generate_graphs_for_llinterp() entrypointptr = cbuild.getentrypointptr() entrygraph = entrypointptr._obj.graph From fijal at codespeak.net Tue Dec 5 12:30:15 2006 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 5 Dec 2006 12:30:15 +0100 (CET) Subject: [pypy-svn] r35285 - pypy/dist/pypy/translator/js/examples Message-ID: <20061205113015.CB07F10070@code0.codespeak.net> Author: fijal Date: Tue Dec 5 12:30:14 2006 New Revision: 35285 Modified: pypy/dist/pypy/translator/js/examples/server.py Log: Moved import thread to support platforms which don't have threads Modified: pypy/dist/pypy/translator/js/examples/server.py ============================================================================== --- pypy/dist/pypy/translator/js/examples/server.py (original) +++ pypy/dist/pypy/translator/js/examples/server.py Tue Dec 5 12:30:14 2006 @@ -17,7 +17,6 @@ from BaseHTTPServer import HTTPServer, BaseHTTPRequestHandler -import thread, threading import re import time import random @@ -104,6 +103,7 @@ httpd = HTTPServer(server_address, handler) if start_new: + import thread thread.start_new_thread(httpd.serve_forever, ()) print "Server started, listening on %s" % (server_address,) else: From fijal at codespeak.net Tue Dec 5 12:51:46 2006 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 5 Dec 2006 12:51:46 +0100 (CET) Subject: [pypy-svn] r35286 - pypy/dist/pypy/translator/js/examples Message-ID: <20061205115146.6ED911007D@code0.codespeak.net> Author: fijal Date: Tue Dec 5 12:51:45 2006 New Revision: 35286 Modified: pypy/dist/pypy/translator/js/examples/server.py Log: Oops Modified: pypy/dist/pypy/translator/js/examples/server.py ============================================================================== --- pypy/dist/pypy/translator/js/examples/server.py (original) +++ pypy/dist/pypy/translator/js/examples/server.py Tue Dec 5 12:51:45 2006 @@ -66,8 +66,8 @@ else: self.serve_data('text/json', json.write(exec_meth(**self.parse_args(getargs)))) else: - outp = method_to_call() - if isinstance(outp, str): + outp = method_to_call(self, **self.parse_args(getargs)) + if isinstance(outp, (str, unicode)): self.serve_data('text/html', outp) elif isinstance(outp, tuple): self.serve_data(*outp) From arigo at codespeak.net Tue Dec 5 13:46:54 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 5 Dec 2006 13:46:54 +0100 (CET) Subject: [pypy-svn] r35294 - pypy/dist/pypy/doc Message-ID: <20061205124654.0042010075@code0.codespeak.net> Author: arigo Date: Tue Dec 5 13:46:52 2006 New Revision: 35294 Modified: pypy/dist/pypy/doc/project-ideas.txt Log: Update this page; add a few #names in the 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 Dec 5 13:46:52 2006 @@ -48,9 +48,8 @@ * lists which are specialised for int-only values (for saving memory). -* some form of caching the lookups of builtin or even global names (most - likely by special forms of dictionaries that can invalidate the caches when - they are written to). +* in-progress: caching the lookups of builtin names (by special forms of + dictionaries that can invalidate the caches when they are written to) * create multiple representations of Unicode string that store the character data in narrower arrays when they can. @@ -108,6 +107,8 @@ We already have a somewhat usable `Prolog interpreter`_ and the beginnings of a `JavaScript interpreter`_. +.. _security: + Investigate restricted execution models --------------------------------------- @@ -123,6 +124,9 @@ objects to be tagged and tracked. The translation of PyPy would also be a good place to insert e.g. systematic checks around all system calls. +.. _distribution: +.. _persistence: + Experiment with distribution and persistence -------------------------------------------- From arigo at codespeak.net Tue Dec 5 13:47:08 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 5 Dec 2006 13:47:08 +0100 (CET) Subject: [pypy-svn] r35295 - pypy/extradoc/sprintinfo/leysin-winter-2007 Message-ID: <20061205124708.60FFF1007D@code0.codespeak.net> Author: arigo Date: Tue Dec 5 13:47:04 2006 New Revision: 35295 Added: pypy/extradoc/sprintinfo/leysin-winter-2007/ (props changed) pypy/extradoc/sprintinfo/leysin-winter-2007/announcement.txt - copied, changed from r35285, pypy/extradoc/sprintinfo/leysin-winter-2006/announcement.txt pypy/extradoc/sprintinfo/leysin-winter-2007/people.txt (contents, props changed) Log: Leysin 2007 announcement. Added: pypy/extradoc/sprintinfo/leysin-winter-2007/people.txt ============================================================================== --- (empty file) +++ pypy/extradoc/sprintinfo/leysin-winter-2007/people.txt Tue Dec 5 13:47:04 2006 @@ -0,0 +1,52 @@ + +People coming to the Leysin sprint Winter 2007 +================================================== + +People who have a ``?`` in their arrive/depart or accomodation +column are known to be coming but there are no details +available yet from them. + +Use ``Accomodation = Ermina`` for the group booking at the Chalets. +Recommended arrival day is the 7th (there might not be enough rooms +available if everybody shows up on the 6th!) + +==================== ============== ===================== + Name Arrive/Depart Accomodation +==================== ============== ===================== +Armin Rigo -- private +Anders Chrigstroem 6th-15th Ermina +Samuele Pedroni 6th-15th Ermina +==================== ============== ===================== + +People on the following list were present at previous sprints: + +==================== ============== ===================== + Name Arrive/Depart Accomodation +==================== ============== ===================== +Holger Krekel ? ? +Christian Tismer ? ? +Michael Hudson ? ? +Anders Lehmann ? ? +Jacob Hallen ? ? +Niklaus Haldimann ? ? +Aurelien Campeas ? ? +Alexandre Fayolle ? ? +Lene Wagner ? ? +Amaury Forgeot d'Arc ? ? +Valentino Volonghi ? ? +Boris Feigin ? ? +Andrew Thompson ? ? +Bert Freudenberg ? ? +Laura Creighton ? ? +Beatrice Duering ? ? +Eric van Riet Paap ? ? +Carl Friedrich Bolz ? ? +Richard Emslie ? ? +Johan Hahn ? ? +Antonio Cuni ? ? +Maciej Fijalkowski ? ? +Stephan Diehl ? ? +Niko Matsakis ? ? +Leonardo Santagada ? ? +Alexander Schremmer ? ? +==================== ============== ===================== From mwh at codespeak.net Tue Dec 5 13:57:32 2006 From: mwh at codespeak.net (mwh at codespeak.net) Date: Tue, 5 Dec 2006 13:57:32 +0100 (CET) Subject: [pypy-svn] r35296 - pypy/extradoc/sprintinfo/leysin-winter-2007 Message-ID: <20061205125732.5A84410075@code0.codespeak.net> Author: mwh Date: Tue Dec 5 13:57:30 2006 New Revision: 35296 Modified: pypy/extradoc/sprintinfo/leysin-winter-2007/announcement.txt Log: a quick review Modified: pypy/extradoc/sprintinfo/leysin-winter-2007/announcement.txt ============================================================================== --- pypy/extradoc/sprintinfo/leysin-winter-2007/announcement.txt (original) +++ pypy/extradoc/sprintinfo/leysin-winter-2007/announcement.txt Tue Dec 5 13:57:30 2006 @@ -14,13 +14,13 @@ http://codespeak.net/pypy/dist/pypy/doc/summer-of-pypy.txt ------------------------------ -Goals and topics of the sprint +Goals and topics of the sprint ------------------------------ * Like previous winter, the main side goal is to have fun in winter - sports :-) We can take a couple of days off for ski; at this period of - the year, ski days end before 4pm, which still leaves plenty of time - for recovering (er, I mean hacking). + sports :-) We can take a couple of days off for ski; at this time of + year, ski days end before 4pm, which still leaves plenty of time + to recover (er, I mean hack). * Progress on the JIT compiler, which we are just starting to scale to the whole of PyPy. `[1]`_ @@ -48,10 +48,10 @@ pair of chalets built specifically for bed & breakfast: http://www.ermina.ch/. The place has a baseline ADSL Internet connexion (600Kb) with wireless installed. You can of course arrange your own -lodging anywhere (you cannot be more than a 15 minutes walk away from -the sprint venue), but I definitely recommend to lodge there too -- you -won't find better sights anywhere else (though you probably won't get -much worse ones easily, either :-) +lodging anywhere (so long as you are in Leysin, you cannot be more than a +15 minute walk away from the sprint venue), but I definitely recommend +lodging there too -- you won't find a better view anywhere else (though you +probably won't get much worse ones easily, either :-) I made pre-reservations in the Chalet, so please *confirm* quickly that you are coming so that we can adjust the reservations as appropriate. @@ -64,6 +64,10 @@ http://codespeak.net/svn/pypy/extradoc/sprintinfo/leysin-winter-2007/people.txt +or on the pypy-sprint mailing list if you do not yet have check-in rights: + + http://codespeak.net/mailman/listinfo/pypy-sprint + ----------- Exact times ----------- From arigo at codespeak.net Tue Dec 5 13:58:04 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 5 Dec 2006 13:58:04 +0100 (CET) Subject: [pypy-svn] r35297 - in pypy/branch/jit-real-world/pypy: jit/codegen/i386/test rpython/lltypesystem Message-ID: <20061205125804.959A81007D@code0.codespeak.net> Author: arigo Date: Tue Dec 5 13:58:02 2006 New Revision: 35297 Modified: pypy/branch/jit-real-world/pypy/jit/codegen/i386/test/test_operation.py pypy/branch/jit-real-world/pypy/rpython/lltypesystem/lloperation.py Log: A skipped test about floats (for later). Modified: pypy/branch/jit-real-world/pypy/jit/codegen/i386/test/test_operation.py ============================================================================== --- pypy/branch/jit-real-world/pypy/jit/codegen/i386/test/test_operation.py (original) +++ pypy/branch/jit-real-world/pypy/jit/codegen/i386/test/test_operation.py Tue Dec 5 13:58:02 2006 @@ -192,3 +192,22 @@ fp = self.rgen(fn, [r_uint, r_uint]) assert fp(40, 2) == fn(40, 2) assert fp(25, 3) == fn(25, 3) + + def test_float_arithmetic(self): + py.test.skip("floats in codegen/i386") + for fn in [lambda x, y: bool(y), + lambda x, y: bool(y - 2.0), + lambda x, y: x + y, + lambda x, y: x - y, + lambda x, y: x * y, + lambda x, y: x / y, + #lambda x, y: x % y, not used? + lambda x, y: x ** y, + lambda x, y: -y, + lambda x, y: ~y, + lambda x, y: abs(y), + lambda x, y: abs(-x), + ]: + fp = self.rgen(fn, [float, float]) + assert fp(40.0, 2.0) == fn(40.0, 2.0) + assert fp(25.125, 1.5) == fn(25.125, 1.5) Modified: pypy/branch/jit-real-world/pypy/rpython/lltypesystem/lloperation.py ============================================================================== --- pypy/branch/jit-real-world/pypy/rpython/lltypesystem/lloperation.py (original) +++ pypy/branch/jit-real-world/pypy/rpython/lltypesystem/lloperation.py Tue Dec 5 13:58:02 2006 @@ -217,8 +217,8 @@ 'float_ne': LLOp(canfold=True), 'float_gt': LLOp(canfold=True), 'float_ge': LLOp(canfold=True), - 'float_floor': LLOp(canfold=True), - 'float_fmod': LLOp(canfold=True), + 'float_floor': LLOp(canfold=True), # XXX not used? + 'float_fmod': LLOp(canfold=True), # XXX not used? 'float_pow': LLOp(canfold=True), 'llong_is_true': LLOp(canfold=True), From arigo at codespeak.net Tue Dec 5 14:22:57 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 5 Dec 2006 14:22:57 +0100 (CET) Subject: [pypy-svn] r35298 - pypy/extradoc/sprintinfo/leysin-winter-2007 Message-ID: <20061205132257.CAA911007D@code0.codespeak.net> Author: arigo Date: Tue Dec 5 14:22:56 2006 New Revision: 35298 Modified: pypy/extradoc/sprintinfo/leysin-winter-2007/announcement.txt Log: Mention power adapters. Modified: pypy/extradoc/sprintinfo/leysin-winter-2007/announcement.txt ============================================================================== --- pypy/extradoc/sprintinfo/leysin-winter-2007/announcement.txt (original) +++ pypy/extradoc/sprintinfo/leysin-winter-2007/announcement.txt Tue Dec 5 14:22:56 2006 @@ -68,6 +68,10 @@ http://codespeak.net/mailman/listinfo/pypy-sprint +You need a Swiss-to-(insert country there) power adapter. There will be +some Swiss-to-EU adapters around - bring a EU-format power strip if you +have one. + ----------- Exact times ----------- From arigo at codespeak.net Tue Dec 5 14:25:10 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 5 Dec 2006 14:25:10 +0100 (CET) Subject: [pypy-svn] r35299 - pypy/extradoc/sprintinfo/leysin-winter-2007 Message-ID: <20061205132510.D19B21007F@code0.codespeak.net> Author: arigo Date: Tue Dec 5 14:25:09 2006 New Revision: 35299 Modified: pypy/extradoc/sprintinfo/leysin-winter-2007/announcement.txt Log: Link to the HTML instead of the TXT. Modified: pypy/extradoc/sprintinfo/leysin-winter-2007/announcement.txt ============================================================================== --- pypy/extradoc/sprintinfo/leysin-winter-2007/announcement.txt (original) +++ pypy/extradoc/sprintinfo/leysin-winter-2007/announcement.txt Tue Dec 5 14:25:09 2006 @@ -11,7 +11,7 @@ The sprint is the last chance for students looking for a "summer" job with PyPy this winter! - http://codespeak.net/pypy/dist/pypy/doc/summer-of-pypy.txt + http://codespeak.net/pypy/dist/pypy/doc/summer-of-pypy.html ------------------------------ Goals and topics of the sprint From mwh at codespeak.net Tue Dec 5 14:27:04 2006 From: mwh at codespeak.net (mwh at codespeak.net) Date: Tue, 5 Dec 2006 14:27:04 +0100 (CET) Subject: [pypy-svn] r35300 - pypy/extradoc/sprintinfo/leysin-winter-2007 Message-ID: <20061205132704.AFEA710084@code0.codespeak.net> Author: mwh Date: Tue Dec 5 14:27:02 2006 New Revision: 35300 Modified: pypy/extradoc/sprintinfo/leysin-winter-2007/announcement.txt Log: typo(?) Modified: pypy/extradoc/sprintinfo/leysin-winter-2007/announcement.txt ============================================================================== --- pypy/extradoc/sprintinfo/leysin-winter-2007/announcement.txt (original) +++ pypy/extradoc/sprintinfo/leysin-winter-2007/announcement.txt Tue Dec 5 14:27:02 2006 @@ -68,7 +68,7 @@ http://codespeak.net/mailman/listinfo/pypy-sprint -You need a Swiss-to-(insert country there) power adapter. There will be +You need a Swiss-to-(insert country here) power adapter. There will be some Swiss-to-EU adapters around - bring a EU-format power strip if you have one. From arigo at codespeak.net Tue Dec 5 15:09:13 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 5 Dec 2006 15:09:13 +0100 (CET) Subject: [pypy-svn] r35301 - in pypy/branch/jit-real-world/pypy: jit/codegen/i386 translator/tool translator/tool/pygame Message-ID: <20061205140913.56CDE1007B@code0.codespeak.net> Author: arigo Date: Tue Dec 5 15:08:43 2006 New Revision: 35301 Added: pypy/branch/jit-real-world/pypy/jit/codegen/i386/autopath.py - copied unchanged from r35295, pypy/branch/jit-real-world/pypy/tool/autopath.py Modified: pypy/branch/jit-real-world/pypy/jit/codegen/i386/codebuf.py pypy/branch/jit-real-world/pypy/jit/codegen/i386/viewcode.py pypy/branch/jit-real-world/pypy/translator/tool/make_dot.py pypy/branch/jit-real-world/pypy/translator/tool/pygame/drawgraph.py pypy/branch/jit-real-world/pypy/translator/tool/pygame/graphclient.py pypy/branch/jit-real-world/pypy/translator/tool/pygame/graphdisplay.py Log: (arre, pedronis, arigo) Dump generated machine code if the PYPYJITLOG env var is set (then it dumps to the file named in $PYPYJITLOG). Improve the viewcode.py viewer to use a fixed-size font and expand the tabs into columns manually. Modified: pypy/branch/jit-real-world/pypy/jit/codegen/i386/codebuf.py ============================================================================== --- pypy/branch/jit-real-world/pypy/jit/codegen/i386/codebuf.py (original) +++ pypy/branch/jit-real-world/pypy/jit/codegen/i386/codebuf.py Tue Dec 5 15:08:43 2006 @@ -2,9 +2,6 @@ from ctypes import POINTER, cast, c_char, c_void_p, CFUNCTYPE, c_int from ri386 import I386CodeBuilder -# Set this to enable/disable the CODE_DUMP stdout lines -CODE_DUMP = False - # ____________________________________________________________ @@ -51,21 +48,46 @@ def done(self): # normally, no special action is needed here - if CODE_DUMP: - self.dump_range(self._last_dump_start, self._pos) - self._last_dump_start = self._pos + if machine_code_dumper.enabled: + machine_code_dumper.dump(self) + - def dump_range(self, start, end): +class MachineCodeDumper: + enabled = True + log_fd = -1 + + def dump(self, cb): + if self.log_fd < 0: + # check the environment for a file name + from pypy.rlib.ros import getenv + s = getenv('PYPYJITLOG') + if not s: + self.enabled = False + return + try: + flags = os.O_WRONLY|os.O_CREAT|os.O_TRUNC + self.log_fd = os.open(s, flags, 0666) + except OSError: + os.write(2, "could not create log file\n") + self.enabled = False + return + self.dump_range(cb, cb._last_dump_start, cb._pos) + cb._last_dump_start = cb._pos + + def dump_range(self, cb, start, end): HEX = '0123456789ABCDEF' dump = [] for p in range(start, end): - o = ord(self._data.contents[p]) + o = ord(cb._data.contents[p]) dump.append(HEX[o >> 4]) dump.append(HEX[o & 15]) if (p & 3) == 3: dump.append(':') - os.write(2, 'CODE_DUMP @%x +%d %s\n' % (self.tell() - self._pos, - start, ''.join(dump))) + line = 'CODE_DUMP @%x +%d %s\n' % (cb.tell() - cb._pos, + start, ''.join(dump)) + os.write(self.log_fd, line) + +machine_code_dumper = MachineCodeDumper() class MachineCodeBlock(InMemoryCodeBuilder): Modified: pypy/branch/jit-real-world/pypy/jit/codegen/i386/viewcode.py ============================================================================== --- pypy/branch/jit-real-world/pypy/jit/codegen/i386/viewcode.py (original) +++ pypy/branch/jit-real-world/pypy/jit/codegen/i386/viewcode.py Tue Dec 5 15:08:43 2006 @@ -8,6 +8,7 @@ /tmp/usession-xxx/testing_1/testing_1 -var 4 2>&1 | ./viewcode.py """ +import autopath import operator, sys, os, re, py # don't use pypy.tool.udir here to avoid removing old usessions which @@ -153,14 +154,40 @@ def show(self): g1 = Graph('codedump') for r in self.ranges: - text = r.disassemble().replace('\t', ' ') + text, width = tab2columns(r.disassemble()) text = '0x%x\n\n%s' % (r.addr, text) - g1.emit_node('N_%x' % r.addr, shape="box", label=text) + g1.emit_node('N_%x' % r.addr, shape="box", label=text, + width=str(width*0.125)) for lineno, targetaddr in r.findjumps(): g1.emit_edge('N_%x' % r.addr, 'N_%x' % targetaddr) g1.display() +def tab2columns(text): + lines = text.split('\n') + columnwidth = [] + for line in lines: + columns = line.split('\t') + while len(columnwidth) < len(columns): + columnwidth.append(0) + for i, s in enumerate(columns): + width = len(s.strip()) + if not s.endswith(':'): + width += 2 + columnwidth[i] = max(columnwidth[i], width) + result = [] + for line in lines: + columns = line.split('\t') + text = [] + for width, s in zip(columnwidth, columns): + text.append(s.strip().ljust(width)) + result.append(' '.join(text)) + if result: + totalwidth = len(result[0]) + else: + totalwidth = 1 + return '\\l'.join(result), totalwidth + # ____________________________________________________________ # XXX pasted from # http://codespeak.net/svn/user/arigo/hack/misc/graphlib.py @@ -201,6 +228,8 @@ return _PageContent(self.graph_builder) class _PageContent: + fixedfont = True + def __init__(self, graph_builder): if callable(graph_builder): graph = graph_builder() Modified: pypy/branch/jit-real-world/pypy/translator/tool/make_dot.py ============================================================================== --- pypy/branch/jit-real-world/pypy/translator/tool/make_dot.py (original) +++ pypy/branch/jit-real-world/pypy/translator/tool/make_dot.py Tue Dec 5 15:08:43 2006 @@ -67,10 +67,11 @@ color="black", fillcolor="white", style="filled", + width="0.75", ): d = locals() attrs = [('%s="%s"' % (x, d[x].replace('"', '\\"').replace('\n', '\\n'))) - for x in ['shape', 'label', 'color', 'fillcolor', 'style']] + for x in ['shape', 'label', 'color', 'fillcolor', 'style', 'width']] self.emit('%s [%s];' % (safename(name), ", ".join(attrs))) Modified: pypy/branch/jit-real-world/pypy/translator/tool/pygame/drawgraph.py ============================================================================== --- pypy/branch/jit-real-world/pypy/translator/tool/pygame/drawgraph.py (original) +++ pypy/branch/jit-real-world/pypy/translator/tool/pygame/drawgraph.py Tue Dec 5 15:08:43 2006 @@ -11,6 +11,7 @@ FONT = os.path.join(autopath.this_dir, 'cyrvetic.ttf') +FIXEDFONT = os.path.join(autopath.this_dir, 'VeraMoBd.ttf') COLOR = { 'black': (0,0,0), 'white': (255,255,255), @@ -52,6 +53,7 @@ class GraphLayout: + fixedfont = False def __init__(self, filename): # parse the layout file (.plain format) @@ -297,7 +299,11 @@ self.FONTCACHE[size] = None return None else: - font = self.FONTCACHE[size] = pygame.font.Font(FONT, size) + if self.graphlayout.fixedfont: + filename = FIXEDFONT + else: + filename = FONT + font = self.FONTCACHE[size] = pygame.font.Font(filename, size) return font def setoffset(self, offsetx, offsety): Modified: pypy/branch/jit-real-world/pypy/translator/tool/pygame/graphclient.py ============================================================================== --- pypy/branch/jit-real-world/pypy/translator/tool/pygame/graphclient.py (original) +++ pypy/branch/jit-real-world/pypy/translator/tool/pygame/graphclient.py Tue Dec 5 15:08:43 2006 @@ -134,6 +134,8 @@ key = page page = page.content() layout = ClientGraphLayout(self, key, page.source, page.links) + if getattr(page, 'fixedfont', False): + layout.fixedfont = True return layout def initiate_display(self, page, link=None, do_display=False): Modified: pypy/branch/jit-real-world/pypy/translator/tool/pygame/graphdisplay.py ============================================================================== --- pypy/branch/jit-real-world/pypy/translator/tool/pygame/graphdisplay.py (original) +++ pypy/branch/jit-real-world/pypy/translator/tool/pygame/graphdisplay.py Tue Dec 5 15:08:43 2006 @@ -3,7 +3,7 @@ import os, time, sys import pygame from pygame.locals import * -from pypy.translator.tool.pygame.drawgraph import GraphRenderer +from pypy.translator.tool.pygame.drawgraph import GraphRenderer, FIXEDFONT from pypy.translator.tool.pygame.drawgraph import Node, Edge from pypy.translator.tool.pygame.drawgraph import EventQueue, wait_for_events @@ -59,7 +59,7 @@ self.screen = pygame.display.set_mode((w, h), HWSURFACE|RESIZABLE, 32) class GraphDisplay(Display): - STATUSBARFONT = os.path.join(autopath.this_dir, 'VeraMoBd.ttf') + STATUSBARFONT = FIXEDFONT ANIM_STEP = 0.07 KEY_REPEAT = (500, 30) STATUSBAR_ALPHA = 0.75 From hpk at codespeak.net Tue Dec 5 15:31:02 2006 From: hpk at codespeak.net (hpk at codespeak.net) Date: Tue, 5 Dec 2006 15:31:02 +0100 (CET) Subject: [pypy-svn] r35302 - pypy/extradoc/sprintinfo/leysin-winter-2007 Message-ID: <20061205143102.CCDA11007F@code0.codespeak.net> Author: hpk Date: Tue Dec 5 15:31:01 2006 New Revision: 35302 Modified: pypy/extradoc/sprintinfo/leysin-winter-2007/announcement.txt Log: small amendments, inserting a deadline for getting proposals. I like the invitation. Modified: pypy/extradoc/sprintinfo/leysin-winter-2007/announcement.txt ============================================================================== --- pypy/extradoc/sprintinfo/leysin-winter-2007/announcement.txt (original) +++ pypy/extradoc/sprintinfo/leysin-winter-2007/announcement.txt Tue Dec 5 15:31:01 2006 @@ -1,5 +1,5 @@ ===================================================================== - Leysin Winter Sprint (8-14th January 2007) + PyPy Leysin Winter Sports Sprint (8-14th January 2007) ===================================================================== .. image:: http://www.ermina.ch/002.JPG @@ -9,7 +9,9 @@ release (scheduled for mid-February). The sprint is the last chance for students looking for a "summer" job -with PyPy this winter! +with PyPy this winter! If you have a proposal and would like to +work with us in the mountains please send it in before 15th December +to "pypy-tb at codespeak.net" and cross-read this page: http://codespeak.net/pypy/dist/pypy/doc/summer-of-pypy.html From cfbolz at codespeak.net Tue Dec 5 16:22:12 2006 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Tue, 5 Dec 2006 16:22:12 +0100 (CET) Subject: [pypy-svn] r35304 - pypy/dist/pypy/interpreter Message-ID: <20061205152212.9E2CE10080@code0.codespeak.net> Author: cfbolz Date: Tue Dec 5 16:22:09 2006 New Revision: 35304 Modified: pypy/dist/pypy/interpreter/baseobjspace.py Log: who would have guessed: this small change makes the testmodule behave in very funny ways! Modified: pypy/dist/pypy/interpreter/baseobjspace.py ============================================================================== --- pypy/dist/pypy/interpreter/baseobjspace.py (original) +++ pypy/dist/pypy/interpreter/baseobjspace.py Tue Dec 5 16:22:09 2006 @@ -171,7 +171,7 @@ # sets all the internal descriptors if config is None: from pypy.config.pypyoption import get_pypy_config - config = get_pypy_config(translating=True) + config = get_pypy_config(translating=False) self.config = config self.interned_strings = {} self.pending_actions = [] From afayolle at codespeak.net Tue Dec 5 16:57:49 2006 From: afayolle at codespeak.net (afayolle at codespeak.net) Date: Tue, 5 Dec 2006 16:57:49 +0100 (CET) Subject: [pypy-svn] r35306 - pypy/dist/pypy/tool/build/bin Message-ID: <20061205155749.083A510081@code0.codespeak.net> Author: afayolle Date: Tue Dec 5 16:57:48 2006 New Revision: 35306 Modified: pypy/dist/pypy/tool/build/bin/client Log: Updated to new option handling scheme Fixed undefined symbol outdir Modified: pypy/dist/pypy/tool/build/bin/client ============================================================================== --- pypy/dist/pypy/tool/build/bin/client (original) +++ pypy/dist/pypy/tool/build/bin/client Tue Dec 5 16:57:48 2006 @@ -50,7 +50,7 @@ # XXX we should compile here, using data dict for info print 'compilation requested for info %r, now faking that' % ( data,) - config = Config(pypyoption.pypy_optiondescription) + config = pypyoption.get_pypy_config() config.override(compileinfo) # XXX compile here... @@ -62,7 +62,7 @@ channelwrapper = ChannelWrapper(channel) zip = ZipFile(channelwrapper, 'w') for fpath in udir.visit(): - zip.writestr(fpath.relto(outdir), fpath.read()) + zip.writestr(fpath.relto(udir), fpath.read()) zip.close() print 'done with compilation, waiting for next' From arigo at codespeak.net Tue Dec 5 17:03:10 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 5 Dec 2006 17:03:10 +0100 (CET) Subject: [pypy-svn] r35308 - pypy/dist/pypy/doc/image Message-ID: <20061205160310.0679310069@code0.codespeak.net> Author: arigo Date: Tue Dec 5 17:03:07 2006 New Revision: 35308 Modified: pypy/dist/pypy/doc/image/ (props changed) Log: ignore the pngs. From arigo at codespeak.net Tue Dec 5 17:06:23 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 5 Dec 2006 17:06:23 +0100 (CET) Subject: [pypy-svn] r35309 - in pypy/dist/pypy/rpython: . ootypesystem Message-ID: <20061205160623.EF34C10069@code0.codespeak.net> Author: arigo Date: Tue Dec 5 17:06:21 2006 New Revision: 35309 Modified: pypy/dist/pypy/rpython/ootypesystem/ooregistry.py pypy/dist/pypy/rpython/ootypesystem/rbuiltin.py pypy/dist/pypy/rpython/ootypesystem/rclass.py pypy/dist/pypy/rpython/ootypesystem/rstr.py pypy/dist/pypy/rpython/rtyper.py Log: (arre, pedronis, arigo) Never never never do 'hop.genop(hop.args_v)'. Modified: pypy/dist/pypy/rpython/ootypesystem/ooregistry.py ============================================================================== --- pypy/dist/pypy/rpython/ootypesystem/ooregistry.py (original) +++ pypy/dist/pypy/rpython/ootypesystem/ooregistry.py Tue Dec 5 17:06:21 2006 @@ -21,8 +21,8 @@ annmodel.SomeFloat, annmodel.SomeOOInstance, annmodel.SomeString)) - assert isinstance(hop.args_s[1], annmodel.SomeInteger) - return hop.genop('oostring', hop.args_v, resulttype = ootype.String) + vlist = hop.inputargs(hop.args_r[0], ootype.Signed) + return hop.genop('oostring', vlist, resulttype = ootype.String) class Entry_ootype_string(ExtRegistryEntry): @@ -44,10 +44,10 @@ def specialize_call(self, hop): assert isinstance(hop.args_s[0], annmodel.SomeOOInstance)\ and hop.args_s[0].ootype is ootype.String - assert isinstance(hop.args_s[1], annmodel.SomeInteger) + vlist = hop.inputargs(hop.args_r[0], ootype.Signed) hop.has_implicit_exception(ValueError) hop.exception_is_here() - return hop.genop('ooparse_int', hop.args_v, resulttype = ootype.Signed) + return hop.genop('ooparse_int', vlist, resulttype = ootype.Signed) class Entry_oohash(ExtRegistryEntry): _about_ = ootype.oohash @@ -60,4 +60,5 @@ def specialize_call(self, hop): assert isinstance(hop.args_s[0], annmodel.SomeOOInstance)\ and hop.args_s[0].ootype is ootype.String - return hop.genop('oohash', hop.args_v, resulttype=ootype.Signed) + vlist = hop.inputargs(hop.args_r[0]) + return hop.genop('oohash', vlist, resulttype=ootype.Signed) Modified: pypy/dist/pypy/rpython/ootypesystem/rbuiltin.py ============================================================================== --- pypy/dist/pypy/rpython/ootypesystem/rbuiltin.py (original) +++ pypy/dist/pypy/rpython/ootypesystem/rbuiltin.py Tue Dec 5 17:06:21 2006 @@ -1,5 +1,5 @@ from pypy.annotation import model as annmodel -from pypy.rpython.ootypesystem import ootype +from pypy.rpython.ootypesystem import ootype, rootype from pypy.rpython.ootypesystem import rclass from pypy.rpython.ootypesystem.rdict import rtype_r_dict from pypy.objspace.flow.model import Constant @@ -20,23 +20,24 @@ def rtype_classof(hop): assert isinstance(hop.args_s[0], annmodel.SomeOOInstance) - return hop.genop('classof', hop.args_v, + vlist = hop.inputargs(hop.args_r[0]) + return hop.genop('classof', vlist, resulttype = ootype.Class) def rtype_subclassof(hop): - assert isinstance(hop.args_s[0], annmodel.SomeOOClass) - assert isinstance(hop.args_s[1], annmodel.SomeOOClass) - return hop.genop('subclassof', hop.args_v, + vlist = hop.inputargs(rootype.ooclass_repr, rootype.ooclass_repr) + return hop.genop('subclassof', vlist, resulttype = ootype.Bool) def rtype_runtimenew(hop): - assert isinstance(hop.args_s[0], annmodel.SomeOOClass) - return hop.genop('runtimenew', hop.args_v, + vlist = hop.inputargs(rootype.ooclass_repr) + return hop.genop('runtimenew', vlist, resulttype = hop.r_result.lowleveltype) def rtype_ooidentityhash(hop): assert isinstance(hop.args_s[0], annmodel.SomeOOInstance) - return hop.genop('ooidentityhash', hop.args_v, + vlist = hop.inputargs(hop.args_r[0]) + return hop.genop('ooidentityhash', vlist, resulttype = ootype.Signed) def rtype_builtin_isinstance(hop): Modified: pypy/dist/pypy/rpython/ootypesystem/rclass.py ============================================================================== --- pypy/dist/pypy/rpython/ootypesystem/rclass.py (original) +++ pypy/dist/pypy/rpython/ootypesystem/rclass.py Tue Dec 5 17:06:21 2006 @@ -399,12 +399,8 @@ vinst, = hop.inputargs(self) return hop.genop('oononnull', [vinst], resulttype=ootype.Bool) - def ll_const(c): - return c - ll_const = staticmethod(ll_const) - def ll_str(self, instance): - return ootype.oostring(instance, self.ll_const(-1)) + return ootype.oostring(instance, -1) def rtype_type(self, hop): if hop.s_result.is_constant(): Modified: pypy/dist/pypy/rpython/ootypesystem/rstr.py ============================================================================== --- pypy/dist/pypy/rpython/ootypesystem/rstr.py (original) +++ pypy/dist/pypy/rpython/ootypesystem/rstr.py Tue Dec 5 17:06:21 2006 @@ -61,11 +61,8 @@ class LLHelpers(AbstractLLHelpers): - def ll_const(c): - return c - def ll_chr2str(ch): - return ootype.oostring(ch, LLHelpers.ll_const(-1)) + return ootype.oostring(ch, -1) def ll_strhash(s): return ootype.oohash(s) Modified: pypy/dist/pypy/rpython/rtyper.py ============================================================================== --- pypy/dist/pypy/rpython/rtyper.py (original) +++ pypy/dist/pypy/rpython/rtyper.py Tue Dec 5 17:06:21 2006 @@ -716,6 +716,8 @@ return vars def genop(self, opname, args_v, resulttype=None): + assert args_v is not self.args_v, ("Wrong level! " + "You need to pass the result of hop.inputargs() to genop().") return self.llops.genop(opname, args_v, resulttype) def gendirectcall(self, ll_function, *args_v): From mwh at codespeak.net Tue Dec 5 17:26:24 2006 From: mwh at codespeak.net (mwh at codespeak.net) Date: Tue, 5 Dec 2006 17:26:24 +0100 (CET) Subject: [pypy-svn] r35312 - in pypy/branch/builtin-call-speedup/pypy: interpreter objspace/std Message-ID: <20061205162624.311A210075@code0.codespeak.net> Author: mwh Date: Tue Dec 5 17:26:24 2006 New Revision: 35312 Modified: pypy/branch/builtin-call-speedup/pypy/interpreter/specialcode.py pypy/branch/builtin-call-speedup/pypy/objspace/std/dictmultiobject.py Log: fix a typo that prevented the WaryDictImplementation from being used, and another that prevented it from working. comment out a print. Modified: pypy/branch/builtin-call-speedup/pypy/interpreter/specialcode.py ============================================================================== --- pypy/branch/builtin-call-speedup/pypy/interpreter/specialcode.py (original) +++ pypy/branch/builtin-call-speedup/pypy/interpreter/specialcode.py Tue Dec 5 17:26:24 2006 @@ -16,8 +16,8 @@ w_builtin_dict = w_builtins.w_dict assert isinstance(w_builtin_dict, W_DictMultiObject) w_value = w_builtin_dict.implementation.get_builtin_indexed(num) - if w_value is not None: - print "CALL_LIKELY_BUILTIN fast" +## if w_value is not None: +## print "CALL_LIKELY_BUILTIN fast" else: w_varname = f.space.wrap(OPTIMIZED_BUILTINS[num]) w_value = f.space.finditem(f.w_globals, w_varname) Modified: pypy/branch/builtin-call-speedup/pypy/objspace/std/dictmultiobject.py ============================================================================== --- pypy/branch/builtin-call-speedup/pypy/objspace/std/dictmultiobject.py (original) +++ pypy/branch/builtin-call-speedup/pypy/objspace/std/dictmultiobject.py Tue Dec 5 17:26:24 2006 @@ -413,6 +413,7 @@ i = BUILTIN_TO_INDEX.get(key, -1) if i != -1: self.shadowed[i] = None + return self elif self._is_sane_hash(w_key_type): raise KeyError else: @@ -630,7 +631,7 @@ def __init__(w_self, space, wary=False): if space.config.objspace.withfastbuiltins and wary: w_self.implementation = WaryDictImplementation(space) - if space.config.objspace.std.withdictmeasurement: + elif space.config.objspace.std.withdictmeasurement: w_self.implementation = MeasuringDictImplementation(space) else: w_self.implementation = space.emptydictimpl From arigo at codespeak.net Tue Dec 5 18:09:36 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 5 Dec 2006 18:09:36 +0100 (CET) Subject: [pypy-svn] r35314 - pypy/dist/pypy/rpython/ootypesystem Message-ID: <20061205170936.26CB510071@code0.codespeak.net> Author: arigo Date: Tue Dec 5 18:09:33 2006 New Revision: 35314 Modified: pypy/dist/pypy/rpython/ootypesystem/ll_str.py Log: (pedronis, arigo) More of these! Removed. Modified: pypy/dist/pypy/rpython/ootypesystem/ll_str.py ============================================================================== --- pypy/dist/pypy/rpython/ootypesystem/ll_str.py (original) +++ pypy/dist/pypy/rpython/ootypesystem/ll_str.py Tue Dec 5 18:09:33 2006 @@ -1,17 +1,14 @@ from pypy.rpython.ootypesystem.ootype import new, oostring, StringBuilder -def const(c): - return c - def ll_int_str(repr, i): return ll_int2dec(i) def ll_int2dec(i): - return oostring(i, const(10)) + return oostring(i, 10) def ll_int2hex(i, addPrefix): if not addPrefix: - return oostring(i, const(16)) + return oostring(i, 16) buf = new(StringBuilder) if i<0: @@ -20,12 +17,12 @@ buf.ll_append_char('0') buf.ll_append_char('x') - buf.ll_append(oostring(i, const(16))) + buf.ll_append(oostring(i, 16)) return buf.ll_build() def ll_int2oct(i, addPrefix): if not addPrefix or i==0: - return oostring(i, const(8)) + return oostring(i, 8) buf = new(StringBuilder) if i<0: @@ -33,8 +30,8 @@ buf.ll_append_char('-') buf.ll_append_char('0') - buf.ll_append(oostring(i, const(8))) + buf.ll_append(oostring(i, 8)) return buf.ll_build() def ll_float_str(repr, f): - return oostring(f, const(-1)) + return oostring(f, -1) From arigo at codespeak.net Tue Dec 5 18:11:42 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 5 Dec 2006 18:11:42 +0100 (CET) Subject: [pypy-svn] r35315 - in pypy/dist/pypy/rpython: . lltypesystem ootypesystem test Message-ID: <20061205171142.E59E310079@code0.codespeak.net> Author: arigo Date: Tue Dec 5 18:11:37 2006 New Revision: 35315 Modified: pypy/dist/pypy/rpython/lltypesystem/rlist.py pypy/dist/pypy/rpython/lltypesystem/rstr.py pypy/dist/pypy/rpython/lltypesystem/rtuple.py pypy/dist/pypy/rpython/ootypesystem/rlist.py pypy/dist/pypy/rpython/ootypesystem/rstr.py pypy/dist/pypy/rpython/ootypesystem/rtuple.py pypy/dist/pypy/rpython/rlist.py pypy/dist/pypy/rpython/rptr.py pypy/dist/pypy/rpython/rtuple.py pypy/dist/pypy/rpython/test/test_rptr.py pypy/dist/pypy/rpython/test/test_rtuple.py Log: (pedronis, arre, arigo) A typesystem-independent way to write ll string building. Allowed us to write ll_str() for lists in a generic way, as well as add ll_str() for tuples and rptrs. Modified: pypy/dist/pypy/rpython/lltypesystem/rlist.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/rlist.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/rlist.py Tue Dec 5 18:11:37 2006 @@ -37,6 +37,7 @@ # class BaseListRepr(AbstractBaseListRepr): + rstr_ll = rstr.LLHelpers def __init__(self, rtyper, item_repr, listitem=None): self.rtyper = rtyper @@ -64,24 +65,6 @@ def make_iterator_repr(self): return ListIteratorRepr(self) - def ll_str(self, l): - items = l.ll_items() - length = l.ll_length() - item_repr = self.item_repr - - temp = malloc(TEMP, length) - i = 0 - while i < length: - temp[i] = item_repr.ll_str(items[i]) - i += 1 - - return rstr.ll_strconcat( - rstr.list_str_open_bracket, - rstr.ll_strconcat(rstr.ll_join(rstr.list_str_sep, - length, - temp), - rstr.list_str_close_bracket)) - def get_itemarray_lowleveltype(self): ITEM = self.item_repr.lowleveltype ITEMARRAY = GcArray(ITEM, @@ -364,8 +347,6 @@ ll_append_noresize.oopspec = 'list.append(l, newitem)' -TEMP = GcArray(Ptr(rstr.STR)) - def ll_both_none(lst1, lst2): return not lst1 and not lst2 Modified: pypy/dist/pypy/rpython/lltypesystem/rstr.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/rstr.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/rstr.py Tue Dec 5 18:11:37 2006 @@ -667,13 +667,33 @@ raise ValueError return sign * val + # interface to build strings: + # x = ll_build_start(n) + # ll_build_push(x, next_string, 0) + # ll_build_push(x, next_string, 1) + # ... + # ll_build_push(x, next_string, n-1) + # s = ll_build_finish(x) + + def ll_build_start(parts_count): + return malloc(TEMP, parts_count) + + def ll_build_push(builder, next_string, index): + builder[index] = next_string + + def ll_build_finish(builder): + return LLHelpers.ll_join_strs(len(builder), builder) + + def ll_constant(s): + return string_repr.convert_const(s) + ll_constant._annspecialcase_ = 'specialize:memo' + def do_stringformat(cls, hop, sourcevarsrepr): s_str = hop.args_s[0] assert s_str.is_constant() s = s_str.const things = cls.parse_fmt_string(s) size = inputconst(Signed, len(things)) # could be unsigned? - TEMP = GcArray(Ptr(STR)) cTEMP = inputconst(Void, TEMP) vtemp = hop.genop("malloc_varsize", [cTEMP, size], resulttype=Ptr(TEMP)) @@ -719,6 +739,8 @@ return hop.gendirectcall(cls.ll_join_strs, size, vtemp) do_stringformat = classmethod(do_stringformat) +TEMP = GcArray(Ptr(STR)) + # TODO: make the public interface of the rstr module cleaner ll_strconcat = LLHelpers.ll_strconcat @@ -771,8 +793,4 @@ unboxed_instance_str_prefix = string_repr.convert_const("") -list_str_open_bracket = string_repr.convert_const("[") -list_str_close_bracket = string_repr.convert_const("]") -list_str_sep = string_repr.convert_const(", ") - percent_f = string_repr.convert_const("%f") Modified: pypy/dist/pypy/rpython/lltypesystem/rtuple.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/rtuple.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/rtuple.py Tue Dec 5 18:11:37 2006 @@ -5,6 +5,7 @@ from pypy.rpython.lltypesystem.lltype import \ Ptr, GcStruct, Void, Signed, malloc, typeOf, nullptr from pypy.rpython.lltypesystem.rtupletype import TUPLE_TYPE +from pypy.rpython.lltypesystem import rstr # ____________________________________________________________ # @@ -18,6 +19,7 @@ # } class TupleRepr(AbstractTupleRepr): + rstr_ll = rstr.LLHelpers def __init__(self, rtyper, items_r): AbstractTupleRepr.__init__(self, rtyper, items_r) Modified: pypy/dist/pypy/rpython/ootypesystem/rlist.py ============================================================================== --- pypy/dist/pypy/rpython/ootypesystem/rlist.py (original) +++ pypy/dist/pypy/rpython/ootypesystem/rlist.py Tue Dec 5 18:11:37 2006 @@ -11,6 +11,7 @@ class BaseListRepr(AbstractBaseListRepr): + rstr_ll = rstr.LLHelpers def __init__(self, rtyper, item_repr, listitem=None): self.rtyper = rtyper @@ -58,24 +59,6 @@ def make_iterator_repr(self): return ListIteratorRepr(self) - def ll_str(self, lst): - item_repr = self.item_repr - length = lst.ll_length() - buf = ootype.new(ootype.StringBuilder) - buf.ll_append_char('[') - i = 0 - while i < length-1: - item = lst.ll_getitem_fast(i) - buf.ll_append(item_repr.ll_str(item)) - buf.ll_append_char(',') - buf.ll_append_char(' ') - i += 1 - if length > 0: - lastitem = lst.ll_getitem_fast(i) - buf.ll_append(item_repr.ll_str(lastitem)) - buf.ll_append_char(']') - return buf.ll_build() - def rtype_hint(self, hop): hints = hop.args_s[-1].const if 'maxlength' in hints: Modified: pypy/dist/pypy/rpython/ootypesystem/rstr.py ============================================================================== --- pypy/dist/pypy/rpython/ootypesystem/rstr.py (original) +++ pypy/dist/pypy/rpython/ootypesystem/rstr.py Tue Dec 5 18:11:37 2006 @@ -193,6 +193,27 @@ raise ValueError return sign * val + # interface to build strings: + # x = ll_build_start(n) + # ll_build_push(x, next_string, 0) + # ll_build_push(x, next_string, 1) + # ... + # ll_build_push(x, next_string, n-1) + # s = ll_build_finish(x) + + def ll_build_start(parts_count): + return ootype.new(ootype.StringBuilder) + + def ll_build_push(buf, next_string, index): + buf.ll_append(next_string) + + def ll_build_finish(buf): + return buf.ll_build() + + def ll_constant(s): + return ootype.make_string(s) + ll_constant._annspecialcase_ = 'specialize:memo' + def do_stringformat(cls, hop, sourcevarsrepr): InstanceRepr = hop.rtyper.type_system.rclass.InstanceRepr string_repr = hop.rtyper.type_system.rstr.string_repr Modified: pypy/dist/pypy/rpython/ootypesystem/rtuple.py ============================================================================== --- pypy/dist/pypy/rpython/ootypesystem/rtuple.py (original) +++ pypy/dist/pypy/rpython/ootypesystem/rtuple.py Tue Dec 5 18:11:37 2006 @@ -1,9 +1,11 @@ from pypy.rpython.rmodel import inputconst from pypy.rpython.rtuple import AbstractTupleRepr, AbstractTupleIteratorRepr from pypy.rpython.ootypesystem import ootype +from pypy.rpython.ootypesystem import rstr class TupleRepr(AbstractTupleRepr): + rstr_ll = rstr.LLHelpers def __init__(self, rtyper, items_r): AbstractTupleRepr.__init__(self, rtyper, items_r) Modified: pypy/dist/pypy/rpython/rlist.py ============================================================================== --- pypy/dist/pypy/rpython/rlist.py (original) +++ pypy/dist/pypy/rpython/rlist.py Tue Dec 5 18:11:37 2006 @@ -84,6 +84,29 @@ def prepare_const(self, nitems): raise NotImplementedError + def ll_str(self, l): + constant = self.rstr_ll.ll_constant + start = self.rstr_ll.ll_build_start + push = self.rstr_ll.ll_build_push + finish = self.rstr_ll.ll_build_finish + + length = l.ll_length() + if length == 0: + return constant("[]") + + buf = start(2 * length + 1) + push(buf, constant("["), 0) + item_repr = self.item_repr + i = 0 + while i < length: + if i > 0: + push(buf, constant(", "), 2 * i) + item = l.ll_getitem_fast(i) + push(buf, item_repr.ll_str(item), 2 * i + 1) + i += 1 + push(buf, constant("]"), 2 * length) + return finish(buf) + def rtype_bltn_list(self, hop): v_lst = hop.inputarg(self, 0) cRESLIST = hop.inputconst(Void, hop.r_result.LIST) Modified: pypy/dist/pypy/rpython/rptr.py ============================================================================== --- pypy/dist/pypy/rpython/rptr.py (original) +++ pypy/dist/pypy/rpython/rptr.py Tue Dec 5 18:11:37 2006 @@ -1,10 +1,10 @@ from pypy.annotation.pairtype import pairtype from pypy.annotation import model as annmodel from pypy.objspace.flow import model as flowmodel -from pypy.rpython.lltypesystem.lltype import \ - Ptr, ContainerType, Void, Signed, Bool, FuncType, typeOf, FixedSizeArray +from pypy.rpython.lltypesystem import lltype from pypy.rpython.error import TyperError from pypy.rpython.rmodel import Repr, IntegerRepr +from pypy.rlib.rarithmetic import r_uint class __extend__(annmodel.SomePtr): @@ -23,33 +23,38 @@ class PtrRepr(Repr): def __init__(self, ptrtype): - assert isinstance(ptrtype, Ptr) + assert isinstance(ptrtype, lltype.Ptr) self.lowleveltype = ptrtype + def ll_str(self, p): + from pypy.rpython.lltypesystem.rstr import LLHelpers, ll_str + id = lltype.cast_ptr_to_int(p) + return ll_str.ll_int2hex(r_uint(id), True) + def rtype_getattr(self, hop): attr = hop.args_s[1].const if isinstance(hop.s_result, annmodel.SomeLLADTMeth): return hop.inputarg(hop.r_result, arg=0) FIELD_TYPE = getattr(self.lowleveltype.TO, attr) - if isinstance(FIELD_TYPE, ContainerType): + if isinstance(FIELD_TYPE, lltype.ContainerType): newopname = 'getsubstruct' else: newopname = 'getfield' - vlist = hop.inputargs(self, Void) + vlist = hop.inputargs(self, lltype.Void) return hop.genop(newopname, vlist, resulttype = hop.r_result.lowleveltype) def rtype_setattr(self, hop): attr = hop.args_s[1].const FIELD_TYPE = getattr(self.lowleveltype.TO, attr) - assert not isinstance(FIELD_TYPE, ContainerType) - vlist = hop.inputargs(self, Void, hop.args_r[2]) + assert not isinstance(FIELD_TYPE, lltype.ContainerType) + vlist = hop.inputargs(self, lltype.Void, hop.args_r[2]) hop.genop('setfield', vlist) def rtype_len(self, hop): ARRAY = hop.args_r[0].lowleveltype.TO - if isinstance(ARRAY, FixedSizeArray): - return hop.inputconst(Signed, ARRAY.length) + if isinstance(ARRAY, lltype.FixedSizeArray): + return hop.inputconst(lltype.Signed, ARRAY.length) else: vlist = hop.inputargs(self) return hop.genop('getarraysize', vlist, @@ -57,10 +62,10 @@ def rtype_is_true(self, hop): vlist = hop.inputargs(self) - return hop.genop('ptr_nonzero', vlist, resulttype=Bool) + return hop.genop('ptr_nonzero', vlist, resulttype=lltype.Bool) def rtype_simple_call(self, hop): - if not isinstance(self.lowleveltype.TO, FuncType): + if not isinstance(self.lowleveltype.TO, lltype.FuncType): raise TyperError("calling a non-function %r", self.lowleveltype.TO) vlist = hop.inputargs(*hop.args_r) nexpected = len(self.lowleveltype.TO.ARGS) @@ -74,7 +79,7 @@ opname = 'direct_call' else: opname = 'indirect_call' - vlist.append(hop.inputconst(Void, None)) + vlist.append(hop.inputconst(lltype.Void, None)) hop.exception_is_here() return hop.genop(opname, vlist, resulttype = self.lowleveltype.TO.RESULT) @@ -92,19 +97,19 @@ def rtype_getitem((r_ptr, r_int), hop): ARRAY = r_ptr.lowleveltype.TO ITEM_TYPE = ARRAY.OF - if isinstance(ITEM_TYPE, ContainerType): + if isinstance(ITEM_TYPE, lltype.ContainerType): newopname = 'getarraysubstruct' else: newopname = 'getarrayitem' - vlist = hop.inputargs(r_ptr, Signed) + vlist = hop.inputargs(r_ptr, lltype.Signed) return hop.genop(newopname, vlist, resulttype = hop.r_result.lowleveltype) def rtype_setitem((r_ptr, r_int), hop): ARRAY = r_ptr.lowleveltype.TO ITEM_TYPE = ARRAY.OF - assert not isinstance(ITEM_TYPE, ContainerType) - vlist = hop.inputargs(r_ptr, Signed, hop.args_r[2]) + assert not isinstance(ITEM_TYPE, lltype.ContainerType) + vlist = hop.inputargs(r_ptr, lltype.Signed, hop.args_r[2]) hop.genop('setarrayitem', vlist) # ____________________________________________________________ @@ -112,10 +117,10 @@ # Null Pointers ##class NullPtrRepr(Repr): -## lowleveltype = Void +## lowleveltype = lltype.Void ## def rtype_is_true(self, hop): -## return hop.inputconst(Bool, False) +## return hop.inputconst(lltype.Bool, False) ##nullptr_repr = NullPtrRepr() @@ -132,22 +137,22 @@ def rtype_eq((r_ptr, r_any), hop): vlist = hop.inputargs(r_ptr, r_ptr) - return hop.genop('ptr_eq', vlist, resulttype=Bool) + return hop.genop('ptr_eq', vlist, resulttype=lltype.Bool) def rtype_ne((r_ptr, r_any), hop): vlist = hop.inputargs(r_ptr, r_ptr) - return hop.genop('ptr_ne', vlist, resulttype=Bool) + return hop.genop('ptr_ne', vlist, resulttype=lltype.Bool) class __extend__(pairtype(Repr, PtrRepr)): def rtype_eq((r_any, r_ptr), hop): vlist = hop.inputargs(r_ptr, r_ptr) - return hop.genop('ptr_eq', vlist, resulttype=Bool) + return hop.genop('ptr_eq', vlist, resulttype=lltype.Bool) def rtype_ne((r_any, r_ptr), hop): vlist = hop.inputargs(r_ptr, r_ptr) - return hop.genop('ptr_ne', vlist, resulttype=Bool) + return hop.genop('ptr_ne', vlist, resulttype=lltype.Bool) # ________________________________________________________________ # ADT methods Modified: pypy/dist/pypy/rpython/rtuple.py ============================================================================== --- pypy/dist/pypy/rpython/rtuple.py (original) +++ pypy/dist/pypy/rpython/rtuple.py Tue Dec 5 18:11:37 2006 @@ -23,6 +23,7 @@ _gen_eq_function_cache = {} _gen_hash_function_cache = {} +_gen_str_function_cache = {} def gen_eq_function(items_r): eq_funcs = [r_item.get_ll_eq_function() or operator.eq for r_item in items_r] @@ -68,6 +69,41 @@ _gen_hash_function_cache[key] = ll_hash return ll_hash +def gen_str_function(tuplerepr): + items_r = tuplerepr.items_r + str_funcs = [r_item.ll_str for r_item in items_r] + key = tuplerepr.rstr_ll, tuple(str_funcs) + try: + return _gen_str_function_cache[key] + except KeyError: + autounrolling_funclist = unrolling_iterable(enumerate(str_funcs)) + + constant = tuplerepr.rstr_ll.ll_constant + start = tuplerepr.rstr_ll.ll_build_start + push = tuplerepr.rstr_ll.ll_build_push + finish = tuplerepr.rstr_ll.ll_build_finish + length = len(items_r) + + def ll_str(t): + if length == 0: + return constant("()") + buf = start(2 * length + 1) + push(buf, constant("("), 0) + for i, str_func in autounrolling_funclist: + attrname = 'item%d' % i + item = getattr(t, attrname) + if i > 0: + push(buf, constant(", "), 2 * i) + push(buf, str_func(item), 2 * i + 1) + if length == 1: + push(buf, constant(",)"), 2 * length) + else: + push(buf, constant(")"), 2 * length) + return finish(buf) + + _gen_str_function_cache[key] = ll_str + return ll_str + class AbstractTupleRepr(Repr): @@ -133,6 +169,8 @@ def get_ll_hash_function(self): return gen_hash_function(self.items_r) + ll_str = property(gen_str_function) + def make_iterator_repr(self): if len(self.items_r) == 1: # subclasses are supposed to set the IteratorRepr attribute Modified: pypy/dist/pypy/rpython/test/test_rptr.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_rptr.py (original) +++ pypy/dist/pypy/rpython/test/test_rptr.py Tue Dec 5 18:11:37 2006 @@ -204,3 +204,15 @@ fptr(*(x,y)) py.test.raises(TypeError, "interpret(wrong, [1, 2])") + + +def test_ptr_str(): + def f(): + return str(p) + + S = GcStruct('S', ('x', Signed)) + p = malloc(S) + + res = interpret(f, []) + assert res.chars[0] == '0' + assert res.chars[1] == 'x' Modified: pypy/dist/pypy/rpython/test/test_rtuple.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_rtuple.py (original) +++ pypy/dist/pypy/rpython/test/test_rtuple.py Tue Dec 5 18:11:37 2006 @@ -286,6 +286,14 @@ res = self.interpret(f, [3]) assert res is True + def test_tuple_str(self): + def f(n): + assert str(()) == "()" + assert str((n,)) == "(%d,)" % n + assert str((n, 6)) == "(%d, 6)" % n + assert str(((n,),)) == "((%d,),)" % n + self.interpret(f, [3]) + class TestLLtype(BaseTestRtuple, LLRtypeMixin): pass From arigo at codespeak.net Tue Dec 5 18:15:56 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 5 Dec 2006 18:15:56 +0100 (CET) Subject: [pypy-svn] r35316 - pypy/dist/pypy/rpython/ootypesystem/test Message-ID: <20061205171556.D643410079@code0.codespeak.net> Author: arigo Date: Tue Dec 5 18:15:54 2006 New Revision: 35316 Modified: pypy/dist/pypy/rpython/ootypesystem/test/test_ooregistry.py pypy/dist/pypy/rpython/ootypesystem/test/test_oortype.py Log: (pedronis, arigo) More! More! Kill! Modified: pypy/dist/pypy/rpython/ootypesystem/test/test_ooregistry.py ============================================================================== --- pypy/dist/pypy/rpython/ootypesystem/test/test_ooregistry.py (original) +++ pypy/dist/pypy/rpython/ootypesystem/test/test_ooregistry.py Tue Dec 5 18:15:54 2006 @@ -21,11 +21,8 @@ assert isinstance(s, annmodel.SomeOOInstance) and s.ootype is ootype.String def test_oostring_call(): - def const(c): - return c - def oof(ch): - return ootype.oostring(ch, const(-1)) + return ootype.oostring(ch, -1) ch = 'a' res = interpret(oof, [ch], type_system='ootype') Modified: pypy/dist/pypy/rpython/ootypesystem/test/test_oortype.py ============================================================================== --- pypy/dist/pypy/rpython/ootypesystem/test/test_oortype.py (original) +++ pypy/dist/pypy/rpython/ootypesystem/test/test_oortype.py Tue Dec 5 18:15:54 2006 @@ -200,11 +200,8 @@ assert interpret(oof, [s], type_system='ootype') == 3 def test_oostring(): - def const(c): - return c - def oof(ch): - return oostring(ch, const(-1)) + return oostring(ch, -1) ch = 'a' res = interpret(oof, [ch], type_system='ootype') From arigo at codespeak.net Tue Dec 5 18:26:06 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 5 Dec 2006 18:26:06 +0100 (CET) Subject: [pypy-svn] r35317 - in pypy/branch/jit-real-world/pypy/rpython: . lltypesystem ootypesystem ootypesystem/test test Message-ID: <20061205172606.859A110088@code0.codespeak.net> Author: arigo Date: Tue Dec 5 18:25:59 2006 New Revision: 35317 Modified: pypy/branch/jit-real-world/pypy/rpython/lltypesystem/rlist.py pypy/branch/jit-real-world/pypy/rpython/lltypesystem/rstr.py pypy/branch/jit-real-world/pypy/rpython/lltypesystem/rtuple.py pypy/branch/jit-real-world/pypy/rpython/ootypesystem/ll_str.py pypy/branch/jit-real-world/pypy/rpython/ootypesystem/rlist.py pypy/branch/jit-real-world/pypy/rpython/ootypesystem/rstr.py pypy/branch/jit-real-world/pypy/rpython/ootypesystem/rtuple.py pypy/branch/jit-real-world/pypy/rpython/ootypesystem/test/test_ooregistry.py pypy/branch/jit-real-world/pypy/rpython/ootypesystem/test/test_oortype.py pypy/branch/jit-real-world/pypy/rpython/rlist.py pypy/branch/jit-real-world/pypy/rpython/rptr.py pypy/branch/jit-real-world/pypy/rpython/rtuple.py pypy/branch/jit-real-world/pypy/rpython/test/test_rptr.py pypy/branch/jit-real-world/pypy/rpython/test/test_rtuple.py Log: (pedronis, arigo) svn merge -r35309:35316 http://codespeak.net/svn/pypy/dist/pypy/rpython Modified: pypy/branch/jit-real-world/pypy/rpython/lltypesystem/rlist.py ============================================================================== --- pypy/branch/jit-real-world/pypy/rpython/lltypesystem/rlist.py (original) +++ pypy/branch/jit-real-world/pypy/rpython/lltypesystem/rlist.py Tue Dec 5 18:25:59 2006 @@ -37,6 +37,7 @@ # class BaseListRepr(AbstractBaseListRepr): + rstr_ll = rstr.LLHelpers def __init__(self, rtyper, item_repr, listitem=None): self.rtyper = rtyper @@ -64,24 +65,6 @@ def make_iterator_repr(self): return ListIteratorRepr(self) - def ll_str(self, l): - items = l.ll_items() - length = l.ll_length() - item_repr = self.item_repr - - temp = malloc(TEMP, length) - i = 0 - while i < length: - temp[i] = item_repr.ll_str(items[i]) - i += 1 - - return rstr.ll_strconcat( - rstr.list_str_open_bracket, - rstr.ll_strconcat(rstr.ll_join(rstr.list_str_sep, - length, - temp), - rstr.list_str_close_bracket)) - def get_itemarray_lowleveltype(self): ITEM = self.item_repr.lowleveltype ITEMARRAY = GcArray(ITEM, @@ -364,8 +347,6 @@ ll_append_noresize.oopspec = 'list.append(l, newitem)' -TEMP = GcArray(Ptr(rstr.STR)) - def ll_both_none(lst1, lst2): return not lst1 and not lst2 Modified: pypy/branch/jit-real-world/pypy/rpython/lltypesystem/rstr.py ============================================================================== --- pypy/branch/jit-real-world/pypy/rpython/lltypesystem/rstr.py (original) +++ pypy/branch/jit-real-world/pypy/rpython/lltypesystem/rstr.py Tue Dec 5 18:25:59 2006 @@ -667,13 +667,33 @@ raise ValueError return sign * val + # interface to build strings: + # x = ll_build_start(n) + # ll_build_push(x, next_string, 0) + # ll_build_push(x, next_string, 1) + # ... + # ll_build_push(x, next_string, n-1) + # s = ll_build_finish(x) + + def ll_build_start(parts_count): + return malloc(TEMP, parts_count) + + def ll_build_push(builder, next_string, index): + builder[index] = next_string + + def ll_build_finish(builder): + return LLHelpers.ll_join_strs(len(builder), builder) + + def ll_constant(s): + return string_repr.convert_const(s) + ll_constant._annspecialcase_ = 'specialize:memo' + def do_stringformat(cls, hop, sourcevarsrepr): s_str = hop.args_s[0] assert s_str.is_constant() s = s_str.const things = cls.parse_fmt_string(s) size = inputconst(Signed, len(things)) # could be unsigned? - TEMP = GcArray(Ptr(STR)) cTEMP = inputconst(Void, TEMP) vtemp = hop.genop("malloc_varsize", [cTEMP, size], resulttype=Ptr(TEMP)) @@ -719,6 +739,8 @@ return hop.gendirectcall(cls.ll_join_strs, size, vtemp) do_stringformat = classmethod(do_stringformat) +TEMP = GcArray(Ptr(STR)) + # TODO: make the public interface of the rstr module cleaner ll_strconcat = LLHelpers.ll_strconcat @@ -771,8 +793,4 @@ unboxed_instance_str_prefix = string_repr.convert_const("") -list_str_open_bracket = string_repr.convert_const("[") -list_str_close_bracket = string_repr.convert_const("]") -list_str_sep = string_repr.convert_const(", ") - percent_f = string_repr.convert_const("%f") Modified: pypy/branch/jit-real-world/pypy/rpython/lltypesystem/rtuple.py ============================================================================== --- pypy/branch/jit-real-world/pypy/rpython/lltypesystem/rtuple.py (original) +++ pypy/branch/jit-real-world/pypy/rpython/lltypesystem/rtuple.py Tue Dec 5 18:25:59 2006 @@ -5,6 +5,7 @@ from pypy.rpython.lltypesystem.lltype import \ Ptr, GcStruct, Void, Signed, malloc, typeOf, nullptr from pypy.rpython.lltypesystem.rtupletype import TUPLE_TYPE +from pypy.rpython.lltypesystem import rstr # ____________________________________________________________ # @@ -18,6 +19,7 @@ # } class TupleRepr(AbstractTupleRepr): + rstr_ll = rstr.LLHelpers def __init__(self, rtyper, items_r): AbstractTupleRepr.__init__(self, rtyper, items_r) Modified: pypy/branch/jit-real-world/pypy/rpython/ootypesystem/ll_str.py ============================================================================== --- pypy/branch/jit-real-world/pypy/rpython/ootypesystem/ll_str.py (original) +++ pypy/branch/jit-real-world/pypy/rpython/ootypesystem/ll_str.py Tue Dec 5 18:25:59 2006 @@ -1,17 +1,14 @@ from pypy.rpython.ootypesystem.ootype import new, oostring, StringBuilder -def const(c): - return c - def ll_int_str(repr, i): return ll_int2dec(i) def ll_int2dec(i): - return oostring(i, const(10)) + return oostring(i, 10) def ll_int2hex(i, addPrefix): if not addPrefix: - return oostring(i, const(16)) + return oostring(i, 16) buf = new(StringBuilder) if i<0: @@ -20,12 +17,12 @@ buf.ll_append_char('0') buf.ll_append_char('x') - buf.ll_append(oostring(i, const(16))) + buf.ll_append(oostring(i, 16)) return buf.ll_build() def ll_int2oct(i, addPrefix): if not addPrefix or i==0: - return oostring(i, const(8)) + return oostring(i, 8) buf = new(StringBuilder) if i<0: @@ -33,8 +30,8 @@ buf.ll_append_char('-') buf.ll_append_char('0') - buf.ll_append(oostring(i, const(8))) + buf.ll_append(oostring(i, 8)) return buf.ll_build() def ll_float_str(repr, f): - return oostring(f, const(-1)) + return oostring(f, -1) Modified: pypy/branch/jit-real-world/pypy/rpython/ootypesystem/rlist.py ============================================================================== --- pypy/branch/jit-real-world/pypy/rpython/ootypesystem/rlist.py (original) +++ pypy/branch/jit-real-world/pypy/rpython/ootypesystem/rlist.py Tue Dec 5 18:25:59 2006 @@ -11,6 +11,7 @@ class BaseListRepr(AbstractBaseListRepr): + rstr_ll = rstr.LLHelpers def __init__(self, rtyper, item_repr, listitem=None): self.rtyper = rtyper @@ -58,24 +59,6 @@ def make_iterator_repr(self): return ListIteratorRepr(self) - def ll_str(self, lst): - item_repr = self.item_repr - length = lst.ll_length() - buf = ootype.new(ootype.StringBuilder) - buf.ll_append_char('[') - i = 0 - while i < length-1: - item = lst.ll_getitem_fast(i) - buf.ll_append(item_repr.ll_str(item)) - buf.ll_append_char(',') - buf.ll_append_char(' ') - i += 1 - if length > 0: - lastitem = lst.ll_getitem_fast(i) - buf.ll_append(item_repr.ll_str(lastitem)) - buf.ll_append_char(']') - return buf.ll_build() - def rtype_hint(self, hop): hints = hop.args_s[-1].const if 'maxlength' in hints: Modified: pypy/branch/jit-real-world/pypy/rpython/ootypesystem/rstr.py ============================================================================== --- pypy/branch/jit-real-world/pypy/rpython/ootypesystem/rstr.py (original) +++ pypy/branch/jit-real-world/pypy/rpython/ootypesystem/rstr.py Tue Dec 5 18:25:59 2006 @@ -196,6 +196,27 @@ raise ValueError return sign * val + # interface to build strings: + # x = ll_build_start(n) + # ll_build_push(x, next_string, 0) + # ll_build_push(x, next_string, 1) + # ... + # ll_build_push(x, next_string, n-1) + # s = ll_build_finish(x) + + def ll_build_start(parts_count): + return ootype.new(ootype.StringBuilder) + + def ll_build_push(buf, next_string, index): + buf.ll_append(next_string) + + def ll_build_finish(buf): + return buf.ll_build() + + def ll_constant(s): + return ootype.make_string(s) + ll_constant._annspecialcase_ = 'specialize:memo' + def do_stringformat(cls, hop, sourcevarsrepr): InstanceRepr = hop.rtyper.type_system.rclass.InstanceRepr string_repr = hop.rtyper.type_system.rstr.string_repr Modified: pypy/branch/jit-real-world/pypy/rpython/ootypesystem/rtuple.py ============================================================================== --- pypy/branch/jit-real-world/pypy/rpython/ootypesystem/rtuple.py (original) +++ pypy/branch/jit-real-world/pypy/rpython/ootypesystem/rtuple.py Tue Dec 5 18:25:59 2006 @@ -1,9 +1,11 @@ from pypy.rpython.rmodel import inputconst from pypy.rpython.rtuple import AbstractTupleRepr, AbstractTupleIteratorRepr from pypy.rpython.ootypesystem import ootype +from pypy.rpython.ootypesystem import rstr class TupleRepr(AbstractTupleRepr): + rstr_ll = rstr.LLHelpers def __init__(self, rtyper, items_r): AbstractTupleRepr.__init__(self, rtyper, items_r) Modified: pypy/branch/jit-real-world/pypy/rpython/ootypesystem/test/test_ooregistry.py ============================================================================== --- pypy/branch/jit-real-world/pypy/rpython/ootypesystem/test/test_ooregistry.py (original) +++ pypy/branch/jit-real-world/pypy/rpython/ootypesystem/test/test_ooregistry.py Tue Dec 5 18:25:59 2006 @@ -21,11 +21,8 @@ assert isinstance(s, annmodel.SomeOOInstance) and s.ootype is ootype.String def test_oostring_call(): - def const(c): - return c - def oof(ch): - return ootype.oostring(ch, const(-1)) + return ootype.oostring(ch, -1) ch = 'a' res = interpret(oof, [ch], type_system='ootype') Modified: pypy/branch/jit-real-world/pypy/rpython/ootypesystem/test/test_oortype.py ============================================================================== --- pypy/branch/jit-real-world/pypy/rpython/ootypesystem/test/test_oortype.py (original) +++ pypy/branch/jit-real-world/pypy/rpython/ootypesystem/test/test_oortype.py Tue Dec 5 18:25:59 2006 @@ -200,11 +200,8 @@ assert interpret(oof, [s], type_system='ootype') == 3 def test_oostring(): - def const(c): - return c - def oof(ch): - return oostring(ch, const(-1)) + return oostring(ch, -1) ch = 'a' res = interpret(oof, [ch], type_system='ootype') Modified: pypy/branch/jit-real-world/pypy/rpython/rlist.py ============================================================================== --- pypy/branch/jit-real-world/pypy/rpython/rlist.py (original) +++ pypy/branch/jit-real-world/pypy/rpython/rlist.py Tue Dec 5 18:25:59 2006 @@ -84,6 +84,29 @@ def prepare_const(self, nitems): raise NotImplementedError + def ll_str(self, l): + constant = self.rstr_ll.ll_constant + start = self.rstr_ll.ll_build_start + push = self.rstr_ll.ll_build_push + finish = self.rstr_ll.ll_build_finish + + length = l.ll_length() + if length == 0: + return constant("[]") + + buf = start(2 * length + 1) + push(buf, constant("["), 0) + item_repr = self.item_repr + i = 0 + while i < length: + if i > 0: + push(buf, constant(", "), 2 * i) + item = l.ll_getitem_fast(i) + push(buf, item_repr.ll_str(item), 2 * i + 1) + i += 1 + push(buf, constant("]"), 2 * length) + return finish(buf) + def rtype_bltn_list(self, hop): v_lst = hop.inputarg(self, 0) cRESLIST = hop.inputconst(Void, hop.r_result.LIST) Modified: pypy/branch/jit-real-world/pypy/rpython/rptr.py ============================================================================== --- pypy/branch/jit-real-world/pypy/rpython/rptr.py (original) +++ pypy/branch/jit-real-world/pypy/rpython/rptr.py Tue Dec 5 18:25:59 2006 @@ -1,10 +1,10 @@ from pypy.annotation.pairtype import pairtype from pypy.annotation import model as annmodel from pypy.objspace.flow import model as flowmodel -from pypy.rpython.lltypesystem.lltype import \ - Ptr, ContainerType, Void, Signed, Bool, FuncType, typeOf, FixedSizeArray +from pypy.rpython.lltypesystem import lltype from pypy.rpython.error import TyperError from pypy.rpython.rmodel import Repr, IntegerRepr +from pypy.rlib.rarithmetic import r_uint class __extend__(annmodel.SomePtr): @@ -23,33 +23,38 @@ class PtrRepr(Repr): def __init__(self, ptrtype): - assert isinstance(ptrtype, Ptr) + assert isinstance(ptrtype, lltype.Ptr) self.lowleveltype = ptrtype + def ll_str(self, p): + from pypy.rpython.lltypesystem.rstr import LLHelpers, ll_str + id = lltype.cast_ptr_to_int(p) + return ll_str.ll_int2hex(r_uint(id), True) + def rtype_getattr(self, hop): attr = hop.args_s[1].const if isinstance(hop.s_result, annmodel.SomeLLADTMeth): return hop.inputarg(hop.r_result, arg=0) FIELD_TYPE = getattr(self.lowleveltype.TO, attr) - if isinstance(FIELD_TYPE, ContainerType): + if isinstance(FIELD_TYPE, lltype.ContainerType): newopname = 'getsubstruct' else: newopname = 'getfield' - vlist = hop.inputargs(self, Void) + vlist = hop.inputargs(self, lltype.Void) return hop.genop(newopname, vlist, resulttype = hop.r_result.lowleveltype) def rtype_setattr(self, hop): attr = hop.args_s[1].const FIELD_TYPE = getattr(self.lowleveltype.TO, attr) - assert not isinstance(FIELD_TYPE, ContainerType) - vlist = hop.inputargs(self, Void, hop.args_r[2]) + assert not isinstance(FIELD_TYPE, lltype.ContainerType) + vlist = hop.inputargs(self, lltype.Void, hop.args_r[2]) hop.genop('setfield', vlist) def rtype_len(self, hop): ARRAY = hop.args_r[0].lowleveltype.TO - if isinstance(ARRAY, FixedSizeArray): - return hop.inputconst(Signed, ARRAY.length) + if isinstance(ARRAY, lltype.FixedSizeArray): + return hop.inputconst(lltype.Signed, ARRAY.length) else: vlist = hop.inputargs(self) return hop.genop('getarraysize', vlist, @@ -57,10 +62,10 @@ def rtype_is_true(self, hop): vlist = hop.inputargs(self) - return hop.genop('ptr_nonzero', vlist, resulttype=Bool) + return hop.genop('ptr_nonzero', vlist, resulttype=lltype.Bool) def rtype_simple_call(self, hop): - if not isinstance(self.lowleveltype.TO, FuncType): + if not isinstance(self.lowleveltype.TO, lltype.FuncType): raise TyperError("calling a non-function %r", self.lowleveltype.TO) vlist = hop.inputargs(*hop.args_r) nexpected = len(self.lowleveltype.TO.ARGS) @@ -74,7 +79,7 @@ opname = 'direct_call' else: opname = 'indirect_call' - vlist.append(hop.inputconst(Void, None)) + vlist.append(hop.inputconst(lltype.Void, None)) hop.exception_is_here() return hop.genop(opname, vlist, resulttype = self.lowleveltype.TO.RESULT) @@ -92,19 +97,19 @@ def rtype_getitem((r_ptr, r_int), hop): ARRAY = r_ptr.lowleveltype.TO ITEM_TYPE = ARRAY.OF - if isinstance(ITEM_TYPE, ContainerType): + if isinstance(ITEM_TYPE, lltype.ContainerType): newopname = 'getarraysubstruct' else: newopname = 'getarrayitem' - vlist = hop.inputargs(r_ptr, Signed) + vlist = hop.inputargs(r_ptr, lltype.Signed) return hop.genop(newopname, vlist, resulttype = hop.r_result.lowleveltype) def rtype_setitem((r_ptr, r_int), hop): ARRAY = r_ptr.lowleveltype.TO ITEM_TYPE = ARRAY.OF - assert not isinstance(ITEM_TYPE, ContainerType) - vlist = hop.inputargs(r_ptr, Signed, hop.args_r[2]) + assert not isinstance(ITEM_TYPE, lltype.ContainerType) + vlist = hop.inputargs(r_ptr, lltype.Signed, hop.args_r[2]) hop.genop('setarrayitem', vlist) # ____________________________________________________________ @@ -112,10 +117,10 @@ # Null Pointers ##class NullPtrRepr(Repr): -## lowleveltype = Void +## lowleveltype = lltype.Void ## def rtype_is_true(self, hop): -## return hop.inputconst(Bool, False) +## return hop.inputconst(lltype.Bool, False) ##nullptr_repr = NullPtrRepr() @@ -132,22 +137,22 @@ def rtype_eq((r_ptr, r_any), hop): vlist = hop.inputargs(r_ptr, r_ptr) - return hop.genop('ptr_eq', vlist, resulttype=Bool) + return hop.genop('ptr_eq', vlist, resulttype=lltype.Bool) def rtype_ne((r_ptr, r_any), hop): vlist = hop.inputargs(r_ptr, r_ptr) - return hop.genop('ptr_ne', vlist, resulttype=Bool) + return hop.genop('ptr_ne', vlist, resulttype=lltype.Bool) class __extend__(pairtype(Repr, PtrRepr)): def rtype_eq((r_any, r_ptr), hop): vlist = hop.inputargs(r_ptr, r_ptr) - return hop.genop('ptr_eq', vlist, resulttype=Bool) + return hop.genop('ptr_eq', vlist, resulttype=lltype.Bool) def rtype_ne((r_any, r_ptr), hop): vlist = hop.inputargs(r_ptr, r_ptr) - return hop.genop('ptr_ne', vlist, resulttype=Bool) + return hop.genop('ptr_ne', vlist, resulttype=lltype.Bool) # ________________________________________________________________ # ADT methods Modified: pypy/branch/jit-real-world/pypy/rpython/rtuple.py ============================================================================== --- pypy/branch/jit-real-world/pypy/rpython/rtuple.py (original) +++ pypy/branch/jit-real-world/pypy/rpython/rtuple.py Tue Dec 5 18:25:59 2006 @@ -23,6 +23,7 @@ _gen_eq_function_cache = {} _gen_hash_function_cache = {} +_gen_str_function_cache = {} def gen_eq_function(items_r): eq_funcs = [r_item.get_ll_eq_function() or operator.eq for r_item in items_r] @@ -68,6 +69,41 @@ _gen_hash_function_cache[key] = ll_hash return ll_hash +def gen_str_function(tuplerepr): + items_r = tuplerepr.items_r + str_funcs = [r_item.ll_str for r_item in items_r] + key = tuplerepr.rstr_ll, tuple(str_funcs) + try: + return _gen_str_function_cache[key] + except KeyError: + autounrolling_funclist = unrolling_iterable(enumerate(str_funcs)) + + constant = tuplerepr.rstr_ll.ll_constant + start = tuplerepr.rstr_ll.ll_build_start + push = tuplerepr.rstr_ll.ll_build_push + finish = tuplerepr.rstr_ll.ll_build_finish + length = len(items_r) + + def ll_str(t): + if length == 0: + return constant("()") + buf = start(2 * length + 1) + push(buf, constant("("), 0) + for i, str_func in autounrolling_funclist: + attrname = 'item%d' % i + item = getattr(t, attrname) + if i > 0: + push(buf, constant(", "), 2 * i) + push(buf, str_func(item), 2 * i + 1) + if length == 1: + push(buf, constant(",)"), 2 * length) + else: + push(buf, constant(")"), 2 * length) + return finish(buf) + + _gen_str_function_cache[key] = ll_str + return ll_str + class AbstractTupleRepr(Repr): @@ -133,6 +169,8 @@ def get_ll_hash_function(self): return gen_hash_function(self.items_r) + ll_str = property(gen_str_function) + def make_iterator_repr(self): if len(self.items_r) == 1: # subclasses are supposed to set the IteratorRepr attribute Modified: pypy/branch/jit-real-world/pypy/rpython/test/test_rptr.py ============================================================================== --- pypy/branch/jit-real-world/pypy/rpython/test/test_rptr.py (original) +++ pypy/branch/jit-real-world/pypy/rpython/test/test_rptr.py Tue Dec 5 18:25:59 2006 @@ -204,3 +204,15 @@ fptr(*(x,y)) py.test.raises(TypeError, "interpret(wrong, [1, 2])") + + +def test_ptr_str(): + def f(): + return str(p) + + S = GcStruct('S', ('x', Signed)) + p = malloc(S) + + res = interpret(f, []) + assert res.chars[0] == '0' + assert res.chars[1] == 'x' Modified: pypy/branch/jit-real-world/pypy/rpython/test/test_rtuple.py ============================================================================== --- pypy/branch/jit-real-world/pypy/rpython/test/test_rtuple.py (original) +++ pypy/branch/jit-real-world/pypy/rpython/test/test_rtuple.py Tue Dec 5 18:25:59 2006 @@ -286,6 +286,14 @@ res = self.interpret(f, [3]) assert res is True + def test_tuple_str(self): + def f(n): + assert str(()) == "()" + assert str((n,)) == "(%d,)" % n + assert str((n, 6)) == "(%d, 6)" % n + assert str(((n,),)) == "((%d,),)" % n + self.interpret(f, [3]) + class TestLLtype(BaseTestRtuple, LLRtypeMixin): pass From cfbolz at codespeak.net Tue Dec 5 18:29:17 2006 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Tue, 5 Dec 2006 18:29:17 +0100 (CET) Subject: [pypy-svn] r35318 - in pypy/dist/pypy: . bin interpreter/pyparser interpreter/pyparser/test tool translator/goal translator/js Message-ID: <20061205172917.29FE210088@code0.codespeak.net> Author: cfbolz Date: Tue Dec 5 18:29:14 2006 New Revision: 35318 Modified: pypy/dist/pypy/bin/jscompile.py pypy/dist/pypy/bin/py.py pypy/dist/pypy/conftest.py pypy/dist/pypy/interpreter/pyparser/pythonparse.py pypy/dist/pypy/interpreter/pyparser/test/stdlib_testall.py pypy/dist/pypy/interpreter/pyparser/test/test_astcompiler.py pypy/dist/pypy/tool/option.py pypy/dist/pypy/translator/goal/targetmultiplespaces.py pypy/dist/pypy/translator/js/main.py Log: yay, kill kill kill code! clean up the mess that tool/option.py was after the introduction of a better way of dealing with configuration. Changes here and there (a lot of them in javascript stuff, I hope I didn't break anything there). Modified: pypy/dist/pypy/bin/jscompile.py ============================================================================== --- pypy/dist/pypy/bin/jscompile.py (original) +++ pypy/dist/pypy/bin/jscompile.py Tue Dec 5 18:29:14 2006 @@ -9,39 +9,20 @@ import autopath import sys, os -from pypy.translator.js.main import rpython2javascript_main, Options +from pypy.translator.js.main import rpython2javascript_main, js_optiondescr -from pypy.tool import option -from py.compat import optparse -make_option = optparse.make_option +from pypy.config.config import Config, to_optparse -def get_options(): - options = [] - config, parser = option.get_standard_options() - - options.append(make_option( - '--view', action='store_true', dest='view', - help='View flow graphs')) - - options.append(make_option( - '--output', action='store', type='string', dest='output', - help='File to save results (default output.js)')) - - options.append(make_option( - '-d', '--debug', action='store_true', dest='debug_transform', - help="Use !EXPERIMENTAL! debug transform to produce tracebacks" - )) - - parser.add_options(options) - return config, parser - def process_options(argv): - config, parser = get_options() - return option.process_options(parser, Options, argv[1:]) + jsconfig = Config(js_optiondescr) + parser, to_optparse(jsconfig) + parser.disable_interspersed_args() + options, args = parser.parse_args(argv) + return args, jsconfig if __name__ == '__main__': - argv = process_options(sys.argv) + args, jsconfig = process_options(sys.argv) curdir = os.getcwd() if curdir not in sys.path: sys.path.insert(0, curdir) - rpython2javascript_main(argv, Options) + rpython2javascript_main(args, jsconfig) Modified: pypy/dist/pypy/bin/py.py ============================================================================== --- pypy/dist/pypy/bin/py.py (original) +++ pypy/dist/pypy/bin/py.py Tue Dec 5 18:29:14 2006 @@ -14,65 +14,36 @@ from pypy.tool import option from py.compat.optparse import make_option from pypy.interpreter import main, interactive, error +from pypy.config.config import OptionDescription, BoolOption, StrOption +from pypy.config.config import Config, to_optparse import os, sys import time -class Options(option.Options): - verbose = os.getenv('PYPY_TB') - interactive = 0 - command = [] - completer = False - module = None - module_args = [] - -def get_main_options(): - config, parser = option.get_standard_options() - - options = [] - options.append(make_option( - '-v', action='store_true', dest='verbose', - help='show verbose interpreter-level traceback')) - - options.append(make_option( - '-C', action='store_true', dest='completer', - help='use readline commandline completer')) - - options.append(make_option( - '-i', action="store_true", dest="interactive", - help="inspect interactively after running script")) - - options.append(make_option( - '-O', action="store_true", dest="optimize", - help="dummy optimization flag for compatibility with C Python")) - - def command_callback(option, opt, value, parser): - parser.values.command = parser.rargs[:] - parser.rargs[:] = [] - - options.append(make_option( - '-c', action="callback", - callback=command_callback, - help="program passed in as CMD (terminates option list)")) - - def runmodule_callback(option, opt, value, parser): - parser.values.module_args = parser.rargs[:] - parser.values.module = value - parser.rargs[:] = [] - - options.append(make_option( - '-m', action="callback", metavar='NAME', - callback=runmodule_callback, type="string", - help="library module to be run as a script (terminates option list)")) - - parser.add_options(options) - - return config, parser +cmdline_optiondescr = OptionDescription("interactive", "the options of py.py", [ + BoolOption("verbose", "show verbose interpreter-level traceback", + default=os.getenv("PYPY_TB"), cmdline="-v"), + BoolOption("interactive", "inspect interactively after running script", + default=False, cmdline="-i"), + BoolOption("completer", "use readline commandline completer", + default=False, cmdline="-C"), + BoolOption("optimize", + "dummy optimization flag for compatibility with C Python", + default=False, cmdline="-O"), + StrOption("runmodule", + "library module to be run as a script (terminates option list)", + default=None, cmdline="-m"), + StrOption("runcommand", + "program passed in as CMD (terminates option list)", + default=None, cmdline="-c"), + ]) def main_(argv=None): starttime = time.time() - config, parser = get_main_options() - args = option.process_options(parser, Options, argv[1:]) - if Options.verbose: + config, parser = option.get_standard_options() + interactiveconfig = Config(cmdline_optiondescr) + to_optparse(interactiveconfig, parser=parser) + args = option.process_options(parser, argv[1:]) + if interactiveconfig.verbose: error.RECORD_INTERPLEVEL_TRACEBACK = True # create the object space @@ -87,21 +58,22 @@ space.setitem(space.sys.w_dict,space.wrap('executable'),space.wrap(argv[0])) # store the command-line arguments into sys.argv - go_interactive = Options.interactive + go_interactive = interactiveconfig.interactive banner = '' exit_status = 0 - if Options.command: - args = ['-c'] + Options.command[1:] + if interactiveconfig.runcommand is not None: + args = ['-c'] + args for arg in args: space.call_method(space.sys.get('argv'), 'append', space.wrap(arg)) # load the source of the program given as command-line argument - if Options.command: + if interactiveconfig.runcommand is not None: def doit(): - main.run_string(Options.command[0], space=space) - elif Options.module: + main.run_string(interactiveconfig.runcommand, space=space) + elif interactiveconfig.runmodule: def doit(): - main.run_module(Options.module, Options.module_args, space=space) + main.run_module(interactiveconfig.runmodule, + args, space=space) elif args: scriptdir = os.path.dirname(os.path.abspath(args[0])) space.call_method(space.sys.get('path'), 'insert', @@ -118,16 +90,18 @@ try: def do_start(): space.startup() - if main.run_toplevel(space, do_start, verbose=Options.verbose): + if main.run_toplevel(space, do_start, + verbose=interactiveconfig.verbose): # compile and run it - if not main.run_toplevel(space, doit, verbose=Options.verbose): + if not main.run_toplevel(space, doit, + verbose=interactiveconfig.verbose): exit_status = 1 # start the interactive console if go_interactive: con = interactive.PyPyConsole( - space, verbose=Options.verbose, - completer=Options.completer) + space, verbose=interactiveconfig.verbose, + completer=interactiveconfig.completer) if banner == '': banner = '%s / %s'%(con.__class__.__name__, repr(space)) @@ -136,7 +110,7 @@ finally: def doit(): space.finish() - main.run_toplevel(space, doit, verbose=Options.verbose) + main.run_toplevel(space, doit, verbose=interactiveconfig.verbose) return exit_status Modified: pypy/dist/pypy/conftest.py ============================================================================== --- pypy/dist/pypy/conftest.py (original) +++ pypy/dist/pypy/conftest.py Tue Dec 5 18:29:14 2006 @@ -1,8 +1,8 @@ import py, sys -from pypy.interpreter.gateway import app2interp_temp +from pypy.interpreter.gateway import app2interp_temp from pypy.interpreter.error import OperationError -from pypy.tool.pytest import appsupport -from pypy.tool.option import make_config +from pypy.tool.pytest import appsupport +from pypy.tool.option import make_config, make_objspace from inspect import isclass, getmro rootdir = py.magic.autopath().dirpath() @@ -13,43 +13,17 @@ # Option = py.test.Config.Option -#class Options: -# group = "pypy options" -# optionlist = - -def usemodules_callback(option, opt, value, parser): - parser.values.usemodules.append(value) - -# XXX these options should go away - -option = py.test.Config.addoptions("pypy options", - Option('-O', '--objspace', action="store", default=None, - type="string", dest="objspace", - help="object space to run tests on."), - Option('--oldstyle', action="store_true",dest="oldstyle", default=False, - help="enable oldstyle classes as default metaclass"), - Option('--nofaking', action="store_true", - dest="nofaking", default=False, - help="avoid faking of modules and objects completely."), - Option('--usemodules', action="callback", type="string", metavar="NAME", - callback=usemodules_callback, default=[], - help="(mixed) modules to use."), - Option('--compiler', action="store", type="string", dest="compiler", - metavar="[ast|cpython]", default='ast', - help="""select compiling approach. see pypy/doc/README.compiling"""), + +option = py.test.Config.addoptions("pypy options", Option('--view', action="store_true", dest="view", default=False, help="view translation tests' flow graphs with Pygame"), - Option('--gc', action="store", default=None, - type="choice", dest="gcpolicy", - choices=['ref', 'boehm', 'none', 'framework', 'exact_boehm'], - help="GcPolicy class to use for genc tests"), - Option('-A', '--runappdirect', action="store_true", + Option('-A', '--runappdirect', action="store_true", default=False, dest="runappdirect", - help="run applevel tests directly on python interpreter (not through PyPy)"), + help="run applevel tests directly on python interpreter (not through PyPy)"), ) _SPACECACHE={} -def getobjspace(name=None, **kwds): +def gettestobjspace(name=None, **kwds): """ helper for instantiating and caching space's for testing. """ config = make_config(option, objspace=name, **kwds) @@ -59,26 +33,23 @@ except KeyError: if option.runappdirect: return TinyObjSpace(**kwds) - mod = __import__('pypy.objspace.%s' % config.objspace.name, - None, None, ['Space']) - Space = mod.Space - try: - space = Space(config) + try: + space = make_objspace(config) except OperationError, e: check_keyboard_interrupt(e) - if option.verbose: - import traceback - traceback.print_exc() + if option.verbose: + import traceback + traceback.print_exc() py.test.fail("fatal: cannot initialize objspace: %r" %(Space,)) _SPACECACHE[key] = space - space.setitem(space.builtin.w_dict, space.wrap('AssertionError'), + space.setitem(space.builtin.w_dict, space.wrap('AssertionError'), appsupport.build_pytest_assertion(space)) space.setitem(space.builtin.w_dict, space.wrap('raises'), space.wrap(appsupport.app_raises)) space.setitem(space.builtin.w_dict, space.wrap('skip'), space.wrap(appsupport.app_skip)) space.raises_w = appsupport.raises_w.__get__(space) - space.eq_w = appsupport.eq_w.__get__(space) + space.eq_w = appsupport.eq_w.__get__(space) return space class TinyObjSpace(object): @@ -188,9 +159,6 @@ else: return IntTestFunction(name, parent=self) -def gettestobjspace(name=None, **kwds): - space = getobjspace(name, **kwds) - return space def skip_on_missing_buildoption(**ropts): __tracebackhide__ = True Modified: pypy/dist/pypy/interpreter/pyparser/pythonparse.py ============================================================================== --- pypy/dist/pypy/interpreter/pyparser/pythonparse.py (original) +++ pypy/dist/pypy/interpreter/pyparser/pythonparse.py Tue Dec 5 18:29:14 2006 @@ -8,7 +8,6 @@ from pypy.interpreter.error import OperationError, debug_print from pypy.interpreter import gateway from pypy.interpreter.pyparser.error import SyntaxError -from pypy.tool.option import Options from pythonlexer import Source, match_encoding_declaration from pypy.interpreter.astcompiler.consts import CO_FUTURE_WITH_STATEMENT import pysymbol @@ -131,8 +130,9 @@ _ver = version return os.path.join( os.path.dirname(__file__), "data", "Grammar" + _ver ), _ver -# unfortunately the command line options are not parsed yet -PYTHON_GRAMMAR, PYPY_VERSION = get_grammar_file( Options.version ) +# unfortunately the command line options are not parsed yet, so it cannot +# be made configurable yet +PYTHON_GRAMMAR, PYPY_VERSION = get_grammar_file("2.5a") def python_grammar(fname): """returns a PythonParser build from the specified grammar file""" 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 Tue Dec 5 18:29:14 2006 @@ -7,7 +7,7 @@ if sys.version[:3] != "2.4": py.test.skip("expected to work only on 2.4") import pypy.conftest - mod.std_space = pypy.conftest.getobjspace('std') + mod.std_space = pypy.conftest.gettestobjspace('std') def check_file_compile(filename): print 'Compiling:', filename Modified: pypy/dist/pypy/interpreter/pyparser/test/test_astcompiler.py ============================================================================== --- pypy/dist/pypy/interpreter/pyparser/test/test_astcompiler.py (original) +++ pypy/dist/pypy/interpreter/pyparser/test/test_astcompiler.py Tue Dec 5 18:29:14 2006 @@ -7,7 +7,7 @@ def setup_module(mod): import pypy.conftest - mod.std_space = pypy.conftest.getobjspace('std') + mod.std_space = pypy.conftest.gettestobjspace('std') from pypy.interpreter.astcompiler import ast, misc, pycodegen Modified: pypy/dist/pypy/tool/option.py ============================================================================== --- pypy/dist/pypy/tool/option.py (original) +++ pypy/dist/pypy/tool/option.py Tue Dec 5 18:29:14 2006 @@ -1,28 +1,14 @@ # This is where the options for py.py are defined. -# XXX needs clean-up and reorganization. import os from pypy.config.pypyoption import get_pypy_config from pypy.config.config import Config, OptionDescription, to_optparse from py.compat import optparse -make_option = optparse.make_option - -class Options: - objspace = "std" - oldstyle = 0 - nofaking = 0 - parser = "pypy" # "cpython" / "pypy" - compiler = "ast" - # "ast" uses interpreter/pyparser & interpreter/astcompiler.py - # "cpython" uses cpython parser and cpython c-level compiler - usemodules = [] - version = "2.5a" # "native" / "2.3" / "2.4" / "2.5a" def run_tb_server(option, opt, value, parser): from pypy.tool import tb_server tb_server.start() - def get_standard_options(): config = get_pypy_config() parser = to_optparse(config, useoptions=["objspace.*"]) @@ -32,65 +18,29 @@ help="use web browser for traceback info") return config, parser -def process_options(op, input_options, argv=None): - global Options - Options = input_options - # backward compatilibity - if isinstance(op, list): - import sys, os - basename = os.path.basename(sys.argv[0]) - config = Config(OptionDescription(basename, basename, [])) - parser = to_optparse(config) - parser.add_options(op) - op = parser - op.disable_interspersed_args() - options, args = op.parse_args(argv, input_options) +def process_options(parser, argv=None): + parser.disable_interspersed_args() + options, args = parser.parse_args(argv) return args def make_config(cmdlineopt, **kwds): """ make a config from cmdline options (which overrides everything) and kwds """ - # XXX this whole file should sooner or later go away and the cmd line - # options be generated from the option description. it's especially messy - # since we have to check whether the default was actually overwritten - conf = get_pypy_config() - if kwds.get("objspace", None) is not None: - conf.objspace.name = kwds["objspace"] - if getattr(cmdlineopt, "objspace", None) is not None: - conf.objspace.name = cmdlineopt.objspace - modnames = getattr(cmdlineopt, "usemodules", '') - if isinstance(modnames, str): - modnames = [mn.strip() for mn in modnames.split(',') if mn.strip()] - for modname in modnames: - setattr(conf.objspace.usemodules, modname, True) - for modname in kwds.get("usemodules", []): - setattr(conf.objspace.usemodules, modname, True) - if getattr(cmdlineopt, "nofaking", False) or kwds.get("nofaking", False): - conf.objspace.nofaking = True - if getattr(cmdlineopt, "oldstyle", False) or kwds.get("oldstyle", False): - conf.objspace.std.oldstyle = True - if hasattr(cmdlineopt, "parser") and cmdlineopt.parser is not None: - conf.objspace.parser = cmdlineopt.parser - if kwds.get("compiler") is not None: - conf.obspace.compiler = kwds['compiler'] - if getattr(cmdlineopt, "compiler", None) is not None: - conf.objspace.compiler = cmdlineopt.compiler - for names, value in kwds.iteritems(): - if "." not in names: - continue - names = names.split(".") - subconf = conf - for name in names[:-1]: - subconf = getattr(subconf, name) - setattr(subconf, names[-1], value) - return conf + config = get_pypy_config(translating=False) + objspace = kwds.pop("objspace", None) + if objspace is not None: + config.objspace.name = objspace + for modname in kwds.pop("usemodules", []): + setattr(config.objspace.usemodules, modname, True) + config.set(**kwds) + return config -def make_objspace(conf): - mod = __import__('pypy.objspace.%s' % conf.objspace.name, +def make_objspace(config): + mod = __import__('pypy.objspace.%s' % config.objspace.name, None, None, ['Space']) Space = mod.Space #conf.objspace.logbytecodes = True - space = Space(conf) - return space + space = Space(config) + return space Modified: pypy/dist/pypy/translator/goal/targetmultiplespaces.py ============================================================================== --- pypy/dist/pypy/translator/goal/targetmultiplespaces.py (original) +++ pypy/dist/pypy/translator/goal/targetmultiplespaces.py Tue Dec 5 18:29:14 2006 @@ -1,7 +1,5 @@ import os, sys -from pypy.tool.option import make_config - from pypy.objspace.std.objspace import StdObjSpace # XXX from pypy.annotation.model import * # since we are execfile()'ed this would pull some Modified: pypy/dist/pypy/translator/js/main.py ============================================================================== --- pypy/dist/pypy/translator/js/main.py (original) +++ pypy/dist/pypy/translator/js/main.py Tue Dec 5 18:29:14 2006 @@ -11,14 +11,21 @@ from pypy.rlib.nonconst import NonConstant from pypy.annotation.policy import AnnotatorPolicy from py.compat import optparse +from pypy.config.config import OptionDescription, BoolOption, StrOption +from pypy.config.config import Config, to_optparse import py -from pypy.tool import option -class Options(option.Options): - view = False - output = 'output.js' - debug_transform = False - use_pdb = True +js_optiondescr = OptionDescription("jscompile", "", [ + BoolOption("view", "View flow graphs", + default=False, cmdline="--view"), + BoolOption("use_pdb", "Use debugger", + default=False, cmdline="--pdb"), + BoolOption("debug_transform", + "Use !EXPERIMENTAL! debug transform to produce tracebacks", + default=False, cmdline="-d --debug"), + StrOption("output", "File to save results (default output.js)", + default="output.js", cmdline="--output")]) + class FunctionNotFound(Exception): pass @@ -39,7 +46,7 @@ return ",".join(func_data.func_code.co_varnames\ [:func_data.func_code.co_argcount]) -def rpython2javascript_main(argv, opts): +def rpython2javascript_main(argv, jsconfig): if len(argv) < 2: print "usage: module " import sys @@ -49,10 +56,9 @@ module_name = module_name[:-3] function_names = argv[1:] mod = __import__(module_name, None, None, ["Module"]) - source = rpython2javascript(mod, function_names, opts=opts) - if opts.output != '': - open(opts.output, "w").write(source) - print "Written file %s" % opts.output + source = rpython2javascript(mod, function_names, jsconfig=jsconfig) + open(jsconfig.output, "w").write(source) + print "Written file %s" % jsconfig.output # some strange function source source_ssf_base = """ @@ -106,7 +112,11 @@ print retval return retval -def rpython2javascript(mod, function_names, opts=Options, use_pdb=True): +def rpython2javascript(mod, function_names, jsconfig=None, use_pdb=True): + if jsconfig is None: + jsconfig = Config(js_optiondescr ) + if use_pdb: + jsconfig.use_pdb = True module_name = mod.__name__ if not function_names and 'main' in mod.__dict__: function_names.append('main') @@ -121,7 +131,8 @@ if func_code.func_code.co_argcount > 0 and func_code.func_code. \ co_argcount != lgt: raise BadSignature("Function %s does not have default arguments" % func_name) - source_ssf = get_source_ssf(mod, module_name, function_names, opts.debug_transform) + source_ssf = get_source_ssf(mod, module_name, function_names, + jsconfig.debug_transform) exec(source_ssf) in globals() # now we gonna just cut off not needed function # XXX: Really do that @@ -129,12 +140,12 @@ #options.debug_transform = opts.debug_transform from pypy.config.pypyoption import get_pypy_config config = get_pypy_config(translating=True) - config.translation.debug_transform = opts.debug_transform + config.translation.debug_transform = jsconfig.debug_transform driver = TranslationDriver(config=config) try: driver.setup(some_strange_function_which_will_never_be_called, [], policy = JsPolicy()) driver.proceed(["compile_js"]) - if opts.view: + if jsconfig.view: driver.translator.view() return driver.gen.tmpfile.open().read() # XXX: Add some possibility to write down selected file From arigo at codespeak.net Tue Dec 5 19:19:09 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 5 Dec 2006 19:19:09 +0100 (CET) Subject: [pypy-svn] r35323 - in pypy/dist/pypy/rpython: . ootypesystem test Message-ID: <20061205181909.EFA5F10077@code0.codespeak.net> Author: arigo Date: Tue Dec 5 19:19:07 2006 New Revision: 35323 Modified: pypy/dist/pypy/rpython/ootypesystem/rstr.py pypy/dist/pypy/rpython/rmodel.py pypy/dist/pypy/rpython/rtyper.py pypy/dist/pypy/rpython/test/test_rlist.py pypy/dist/pypy/rpython/test/test_rstr.py Log: (pedronis, arigo) Fix %-formatting of lists and tuples, a bit here and there. Modified: pypy/dist/pypy/rpython/ootypesystem/rstr.py ============================================================================== --- pypy/dist/pypy/rpython/ootypesystem/rstr.py (original) +++ pypy/dist/pypy/rpython/ootypesystem/rstr.py Tue Dec 5 19:19:07 2006 @@ -238,9 +238,8 @@ vitem, r_arg = argsiter.next() if not hasattr(r_arg, 'll_str'): raise TyperError("ll_str unsupported for: %r" % r_arg) - if code == 's': - # TODO: for now it works only with types supported by oostring - vchunk = hop.genop('oostring', [vitem, cm1], resulttype=ootype.String) + if code == 's' or (code == 'r' and isinstance(r_arg, InstanceRepr)): + vchunk = hop.gendirectcall(r_arg.ll_str, vitem) elif code == 'd': assert isinstance(r_arg, IntegerRepr) vchunk = hop.genop('oostring', [vitem, c10], resulttype=ootype.String) @@ -253,8 +252,6 @@ elif code == 'o': assert isinstance(r_arg, IntegerRepr) vchunk = hop.genop('oostring', [vitem, c8], resulttype=ootype.String) - elif code == 'r' and isinstance(r_arg, InstanceRepr): - vchunk = hop.gendirectcall(r_arg.ll_str, vitem) else: raise TyperError, "%%%s is not RPython" % (code, ) else: Modified: pypy/dist/pypy/rpython/rmodel.py ============================================================================== --- pypy/dist/pypy/rpython/rmodel.py (original) +++ pypy/dist/pypy/rpython/rmodel.py Tue Dec 5 19:19:07 2006 @@ -353,6 +353,7 @@ def get_ll_eq_function(self): return None def get_ll_hash_function(self): return ll_hash_void get_ll_fasthash_function = get_ll_hash_function + def ll_str(self, nothing): raise AssertionError("unreachable code") impossible_repr = VoidRepr() class SimplePointerRepr(Repr): Modified: pypy/dist/pypy/rpython/rtyper.py ============================================================================== --- pypy/dist/pypy/rpython/rtyper.py (original) +++ pypy/dist/pypy/rpython/rtyper.py Tue Dec 5 19:19:07 2006 @@ -846,7 +846,7 @@ newargs_v = [] for v in args_v: if v.concretetype is Void: - s_value = rtyper.binding(v) + s_value = rtyper.binding(v, default=annmodel.s_None) if not s_value.is_constant(): raise TyperError("non-constant variable of type Void") if not isinstance(s_value, annmodel.SomePBC): Modified: pypy/dist/pypy/rpython/test/test_rlist.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_rlist.py (original) +++ pypy/dist/pypy/rpython/test/test_rlist.py Tue Dec 5 19:19:07 2006 @@ -735,6 +735,12 @@ res = self.interpret(fn, []) assert self.ll_to_string(res) == fn() + def fn(): + return str([]) + + res = self.interpret(fn, []) + assert self.ll_to_string(res) == fn() + def test_list_or_None(self): empty_list = [] nonempty_list = [1, 2] Modified: pypy/dist/pypy/rpython/test/test_rstr.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_rstr.py (original) +++ pypy/dist/pypy/rpython/test/test_rstr.py Tue Dec 5 19:19:07 2006 @@ -472,6 +472,32 @@ res = res.replace('pypy.rpython.test.test_rstr.', '') assert res == 'what a nice , much nicer than ' + def test_percentformat_tuple(self): + for t, expected in [((), "<<<()>>>"), + ((5,), "<<<(5,)>>>"), + ((5, 6), "<<<(5, 6)>>>"), + ((5, 6, 7), "<<<(5, 6, 7)>>>")]: + def getter(): + return t + def dummy(): + return "<<<%s>>>" % (getter(),) + + res = self.ll_to_string(self.interpret(dummy, [])) + assert res == expected + + def test_percentformat_list(self): + for t, expected in [([], "<<<[]>>>"), + ([5], "<<<[5]>>>"), + ([5, 6], "<<<[5, 6]>>>"), + ([5, 6, 7], "<<<[5, 6, 7]>>>")]: + def getter(): + return t + def dummy(): + return "<<<%s>>>" % (getter(),) + + res = self.ll_to_string(self.interpret(dummy, [])) + assert res == expected + def test_split(self): def fn(i): s = ['', '0.1.2.4.8', '.1.2', '1.2.', '.1.2.4.'][i] From arigo at codespeak.net Tue Dec 5 19:20:24 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 5 Dec 2006 19:20:24 +0100 (CET) Subject: [pypy-svn] r35324 - in pypy/branch/jit-real-world/pypy/rpython: . ootypesystem test Message-ID: <20061205182024.A940010078@code0.codespeak.net> Author: arigo Date: Tue Dec 5 19:20:22 2006 New Revision: 35324 Modified: pypy/branch/jit-real-world/pypy/rpython/ootypesystem/rstr.py pypy/branch/jit-real-world/pypy/rpython/rmodel.py pypy/branch/jit-real-world/pypy/rpython/rtyper.py pypy/branch/jit-real-world/pypy/rpython/test/test_rlist.py pypy/branch/jit-real-world/pypy/rpython/test/test_rstr.py Log: svn merge -r35317:35323 http://codespeak.net/svn/pypy/dist/pypy/rpython Modified: pypy/branch/jit-real-world/pypy/rpython/ootypesystem/rstr.py ============================================================================== --- pypy/branch/jit-real-world/pypy/rpython/ootypesystem/rstr.py (original) +++ pypy/branch/jit-real-world/pypy/rpython/ootypesystem/rstr.py Tue Dec 5 19:20:22 2006 @@ -241,9 +241,8 @@ vitem, r_arg = argsiter.next() if not hasattr(r_arg, 'll_str'): raise TyperError("ll_str unsupported for: %r" % r_arg) - if code == 's': - # TODO: for now it works only with types supported by oostring - vchunk = hop.genop('oostring', [vitem, cm1], resulttype=ootype.String) + if code == 's' or (code == 'r' and isinstance(r_arg, InstanceRepr)): + vchunk = hop.gendirectcall(r_arg.ll_str, vitem) elif code == 'd': assert isinstance(r_arg, IntegerRepr) vchunk = hop.genop('oostring', [vitem, c10], resulttype=ootype.String) @@ -256,8 +255,6 @@ elif code == 'o': assert isinstance(r_arg, IntegerRepr) vchunk = hop.genop('oostring', [vitem, c8], resulttype=ootype.String) - elif code == 'r' and isinstance(r_arg, InstanceRepr): - vchunk = hop.gendirectcall(r_arg.ll_str, vitem) else: raise TyperError, "%%%s is not RPython" % (code, ) else: Modified: pypy/branch/jit-real-world/pypy/rpython/rmodel.py ============================================================================== --- pypy/branch/jit-real-world/pypy/rpython/rmodel.py (original) +++ pypy/branch/jit-real-world/pypy/rpython/rmodel.py Tue Dec 5 19:20:22 2006 @@ -353,6 +353,7 @@ def get_ll_eq_function(self): return None def get_ll_hash_function(self): return ll_hash_void get_ll_fasthash_function = get_ll_hash_function + def ll_str(self, nothing): raise AssertionError("unreachable code") impossible_repr = VoidRepr() class SimplePointerRepr(Repr): Modified: pypy/branch/jit-real-world/pypy/rpython/rtyper.py ============================================================================== --- pypy/branch/jit-real-world/pypy/rpython/rtyper.py (original) +++ pypy/branch/jit-real-world/pypy/rpython/rtyper.py Tue Dec 5 19:20:22 2006 @@ -849,7 +849,7 @@ newargs_v = [] for v in args_v: if v.concretetype is Void: - s_value = rtyper.binding(v) + s_value = rtyper.binding(v, default=annmodel.s_None) if not s_value.is_constant(): raise TyperError("non-constant variable of type Void") if not isinstance(s_value, annmodel.SomePBC): Modified: pypy/branch/jit-real-world/pypy/rpython/test/test_rlist.py ============================================================================== --- pypy/branch/jit-real-world/pypy/rpython/test/test_rlist.py (original) +++ pypy/branch/jit-real-world/pypy/rpython/test/test_rlist.py Tue Dec 5 19:20:22 2006 @@ -735,6 +735,12 @@ res = self.interpret(fn, []) assert self.ll_to_string(res) == fn() + def fn(): + return str([]) + + res = self.interpret(fn, []) + assert self.ll_to_string(res) == fn() + def test_list_or_None(self): empty_list = [] nonempty_list = [1, 2] Modified: pypy/branch/jit-real-world/pypy/rpython/test/test_rstr.py ============================================================================== --- pypy/branch/jit-real-world/pypy/rpython/test/test_rstr.py (original) +++ pypy/branch/jit-real-world/pypy/rpython/test/test_rstr.py Tue Dec 5 19:20:22 2006 @@ -472,6 +472,32 @@ res = res.replace('pypy.rpython.test.test_rstr.', '') assert res == 'what a nice , much nicer than ' + def test_percentformat_tuple(self): + for t, expected in [((), "<<<()>>>"), + ((5,), "<<<(5,)>>>"), + ((5, 6), "<<<(5, 6)>>>"), + ((5, 6, 7), "<<<(5, 6, 7)>>>")]: + def getter(): + return t + def dummy(): + return "<<<%s>>>" % (getter(),) + + res = self.ll_to_string(self.interpret(dummy, [])) + assert res == expected + + def test_percentformat_list(self): + for t, expected in [([], "<<<[]>>>"), + ([5], "<<<[5]>>>"), + ([5, 6], "<<<[5, 6]>>>"), + ([5, 6, 7], "<<<[5, 6, 7]>>>")]: + def getter(): + return t + def dummy(): + return "<<<%s>>>" % (getter(),) + + res = self.ll_to_string(self.interpret(dummy, [])) + assert res == expected + def test_split(self): def fn(i): s = ['', '0.1.2.4.8', '.1.2', '1.2.', '.1.2.4.'][i] From arigo at codespeak.net Tue Dec 5 19:23:06 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 5 Dec 2006 19:23:06 +0100 (CET) Subject: [pypy-svn] r35325 - in pypy/branch/jit-real-world/pypy/jit: codegen codegen/i386 timeshifter Message-ID: <20061205182306.90A0E10077@code0.codespeak.net> Author: arigo Date: Tue Dec 5 19:23:03 2006 New Revision: 35325 Modified: pypy/branch/jit-real-world/pypy/jit/codegen/i386/codebuf.py pypy/branch/jit-real-world/pypy/jit/codegen/i386/rgenop.py pypy/branch/jit-real-world/pypy/jit/codegen/model.py pypy/branch/jit-real-world/pypy/jit/timeshifter/rtimeshift.py Log: (pedronis, arigo) Log the start_new_blocks of global merge points, for debugging. Modified: pypy/branch/jit-real-world/pypy/jit/codegen/i386/codebuf.py ============================================================================== --- pypy/branch/jit-real-world/pypy/jit/codegen/i386/codebuf.py (original) +++ pypy/branch/jit-real-world/pypy/jit/codegen/i386/codebuf.py Tue Dec 5 19:23:03 2006 @@ -49,30 +49,41 @@ def done(self): # normally, no special action is needed here if machine_code_dumper.enabled: - machine_code_dumper.dump(self) + machine_code_dumper.dump_range(self, self._last_dump_start, + self._pos) + self._last_dump_start = self._pos + + def log(self, msg): + if machine_code_dumper.enabled: + machine_code_dumper.dump(self, 'LOG', self._pos, msg) class MachineCodeDumper: enabled = True log_fd = -1 - def dump(self, cb): + def open(self): if self.log_fd < 0: # check the environment for a file name from pypy.rlib.ros import getenv s = getenv('PYPYJITLOG') if not s: self.enabled = False - return + return False try: flags = os.O_WRONLY|os.O_CREAT|os.O_TRUNC self.log_fd = os.open(s, flags, 0666) except OSError: os.write(2, "could not create log file\n") self.enabled = False - return - self.dump_range(cb, cb._last_dump_start, cb._pos) - cb._last_dump_start = cb._pos + return False + return True + + def dump(self, cb, tag, pos, msg): + if not self.open(): + return + line = '%s @%x +%d %s\n' % (tag, cb.tell() - cb._pos, pos, msg) + os.write(self.log_fd, line) def dump_range(self, cb, start, end): HEX = '0123456789ABCDEF' @@ -83,9 +94,7 @@ dump.append(HEX[o & 15]) if (p & 3) == 3: dump.append(':') - line = 'CODE_DUMP @%x +%d %s\n' % (cb.tell() - cb._pos, - start, ''.join(dump)) - os.write(self.log_fd, line) + self.dump(cb, 'CODE_DUMP', start, ''.join(dump)) machine_code_dumper = MachineCodeDumper() Modified: pypy/branch/jit-real-world/pypy/jit/codegen/i386/rgenop.py ============================================================================== --- pypy/branch/jit-real-world/pypy/jit/codegen/i386/rgenop.py (original) +++ pypy/branch/jit-real-world/pypy/jit/codegen/i386/rgenop.py Tue Dec 5 19:23:03 2006 @@ -422,6 +422,9 @@ def show_incremental_progress(self): pass + def log(self, msg): + self.mc.log(msg) + # ____________________________________________________________ def stack_access(self, stackpos): Modified: pypy/branch/jit-real-world/pypy/jit/codegen/model.py ============================================================================== --- pypy/branch/jit-real-world/pypy/jit/codegen/model.py (original) +++ pypy/branch/jit-real-world/pypy/jit/codegen/model.py Tue Dec 5 19:23:03 2006 @@ -138,6 +138,11 @@ So far, the machine code backends don\'t actually do anything for this. ''' + def log(self, msg): + '''Optional method: prints or logs the position of the generated code + along with the given msg. + ''' + class GenLabel(object): '''A "smart" label. Represents an address of the start of a basic block and the location of the inputargs on entry to that block.''' Modified: pypy/branch/jit-real-world/pypy/jit/timeshifter/rtimeshift.py ============================================================================== --- pypy/branch/jit-real-world/pypy/jit/timeshifter/rtimeshift.py (original) +++ pypy/branch/jit-real-world/pypy/jit/timeshifter/rtimeshift.py Tue Dec 5 19:23:03 2006 @@ -221,12 +221,13 @@ assert res, "exactmatch() failed" cleanup_partial_data(memo.partialdatamatch) newblock = enter_next_block(jitstate, outgoingvarboxes) - if index == -1: + if index < 0: states_dic[key].append((frozen, newblock)) else: states_dic[key][index] = (frozen, newblock) if global_resumer is not None and global_resumer is not return_marker: + jitstate.curbuilder.log('start_new_block %s' % (key,)) greens_gv = jitstate.greens rgenop = jitstate.curbuilder.rgenop node = PromotionPathRoot(greens_gv, rgenop, From fijal at codespeak.net Tue Dec 5 20:13:43 2006 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 5 Dec 2006 20:13:43 +0100 (CET) Subject: [pypy-svn] r35329 - in pypy/dist/pypy/translator/js/examples: . test Message-ID: <20061205191343.B193510077@code0.codespeak.net> Author: fijal Date: Tue Dec 5 20:13:40 2006 New Revision: 35329 Added: pypy/dist/pypy/translator/js/examples/test/ pypy/dist/pypy/translator/js/examples/test/__init__.py (contents, props changed) pypy/dist/pypy/translator/js/examples/test/test_server.py (contents, props changed) Modified: pypy/dist/pypy/translator/js/examples/server.py Log: Argh. I'm fed up with stuff accidentally stopping working. Adding test (more to come...) Modified: pypy/dist/pypy/translator/js/examples/server.py ============================================================================== --- pypy/dist/pypy/translator/js/examples/server.py (original) +++ pypy/dist/pypy/translator/js/examples/server.py Tue Dec 5 20:13:40 2006 @@ -29,10 +29,10 @@ from pypy.rpython.ootypesystem.bltregistry import MethodDesc, BasicExternal,\ described -from pypy.translator.js.main import rpython2javascript, Options +from pypy.translator.js.main import rpython2javascript, js_optiondescr from pypy.translator.js import commproxy -Options.debug_transform = False +js_optiondescr.debug_transform = False commproxy.USE_MOCHIKIT = True class ExportedMethods(BasicExternal): @@ -66,7 +66,7 @@ else: self.serve_data('text/json', json.write(exec_meth(**self.parse_args(getargs)))) else: - outp = method_to_call(self, **self.parse_args(getargs)) + outp = method_to_call(**self.parse_args(getargs)) if isinstance(outp, (str, unicode)): self.serve_data('text/html', outp) elif isinstance(outp, tuple): Added: pypy/dist/pypy/translator/js/examples/test/__init__.py ============================================================================== Added: pypy/dist/pypy/translator/js/examples/test/test_server.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/translator/js/examples/test/test_server.py Tue Dec 5 20:13:40 2006 @@ -0,0 +1,19 @@ + +""" Server testing +""" + +from pypy.translator.js.examples import server +from urllib import URLopener + +class Handler(server.TestHandler): + def index(self): + return "xxx" + index.exposed = True + +def test_basic_startup(): + import thread + # XXX: how to do this without threads? + httpd = server.HTTPServer(('127.0.0.1', 21210), Handler) + thread.start_new_thread(httpd.serve_forever, ()) + assert URLopener().open("http://127.0.0.1:21210/index").read() == "xxx" + From ericvrp at codespeak.net Tue Dec 5 20:42:21 2006 From: ericvrp at codespeak.net (ericvrp at codespeak.net) Date: Tue, 5 Dec 2006 20:42:21 +0100 (CET) Subject: [pypy-svn] r35331 - pypy/dist/pypy/jit/codegen/llvm/lib Message-ID: <20061205194221.557B610078@code0.codespeak.net> Author: ericvrp Date: Tue Dec 5 20:42:19 2006 New Revision: 35331 Modified: pypy/dist/pypy/jit/codegen/llvm/lib/libllvmjit.cpp pypy/dist/pypy/jit/codegen/llvm/lib/libllvmjit.h Log: Added function to get to the actual function pointer that we feed into rctypes later Modified: pypy/dist/pypy/jit/codegen/llvm/lib/libllvmjit.cpp ============================================================================== --- pypy/dist/pypy/jit/codegen/llvm/lib/libllvmjit.cpp (original) +++ pypy/dist/pypy/jit/codegen/llvm/lib/libllvmjit.cpp Tue Dec 5 20:42:19 2006 @@ -87,13 +87,19 @@ //Function methods -int freeMachineCodeForFunction(const void* function) { - if (!function) { +void* getPointerToFunction(const void* p_function) { + //note: this forces JIT compilation + return gp_execution_engine->getPointerToFunction((Function*)p_function); +} + + +int freeMachineCodeForFunction(const void* p_function) { + if (!p_function) { std::cerr << "No function supplied to libllvmjit.freeMachineCodeForFunction(...)\n" << std::flush; return 0; } - gp_execution_engine->freeMachineCodeForFunction((Function*)function); + gp_execution_engine->freeMachineCodeForFunction((Function*)p_function); return 1; } Modified: pypy/dist/pypy/jit/codegen/llvm/lib/libllvmjit.h ============================================================================== --- pypy/dist/pypy/jit/codegen/llvm/lib/libllvmjit.h (original) +++ pypy/dist/pypy/jit/codegen/llvm/lib/libllvmjit.h Tue Dec 5 20:42:19 2006 @@ -9,7 +9,8 @@ int parse(const char* llsource); //Function code -int freeMachineCodeForFunction(const void* function); +void* getPointerToFunction(const void* p_function); +int freeMachineCodeForFunction(const void* p_function); int recompile(const void* function); int execute(const void* function, int param); From ericvrp at codespeak.net Tue Dec 5 20:43:54 2006 From: ericvrp at codespeak.net (ericvrp at codespeak.net) Date: Tue, 5 Dec 2006 20:43:54 +0100 (CET) Subject: [pypy-svn] r35332 - in pypy/dist/pypy/jit/codegen/llvm: . test Message-ID: <20061205194354.B5F4710080@code0.codespeak.net> Author: ericvrp Date: Tue Dec 5 20:43:53 2006 New Revision: 35332 Modified: pypy/dist/pypy/jit/codegen/llvm/llvmjit.py pypy/dist/pypy/jit/codegen/llvm/rgenop.py pypy/dist/pypy/jit/codegen/llvm/test/test_llvmjit.py pypy/dist/pypy/jit/codegen/llvm/test/test_rgenop.py Log: First jit/codegen/llvm rgenop test that actualy passes Modified: pypy/dist/pypy/jit/codegen/llvm/llvmjit.py ============================================================================== --- pypy/dist/pypy/jit/codegen/llvm/llvmjit.py (original) +++ pypy/dist/pypy/jit/codegen/llvm/llvmjit.py Tue Dec 5 20:43:53 2006 @@ -44,6 +44,9 @@ libraries = (os.path.join(os.path.dirname(path), 'llvmjit'),) llvmjit._FuncPtr = _FuncPtr +#ensure stable state +llvmjit.restart() + #exposed functions... restart = llvmjit.restart @@ -63,6 +66,10 @@ getNamedGlobal.restype = c_void_p getNamedGlobal.argtypes = [c_char_p] +getPointerToFunction = llvmjit.getPointerToFunction +getPointerToFunction.restype = c_void_p +getPointerToFunction.argtypes = [c_void_p] + freeMachineCodeForFunction = llvmjit.freeMachineCodeForFunction freeMachineCodeForFunction.restype = c_int freeMachineCodeForFunction.argtypes = [c_void_p] Modified: pypy/dist/pypy/jit/codegen/llvm/rgenop.py ============================================================================== --- pypy/dist/pypy/jit/codegen/llvm/rgenop.py (original) +++ pypy/dist/pypy/jit/codegen/llvm/rgenop.py Tue Dec 5 20:43:53 2006 @@ -2,6 +2,7 @@ from pypy.rpython.lltypesystem import lltype, llmemory from pypy.jit.codegen.model import AbstractRGenOp, GenLabel, GenBuilder from pypy.jit.codegen.model import GenVar, GenConst, CodeGenSwitch +from pypy.jit.codegen.llvm import llvmjit def log(s): @@ -9,10 +10,20 @@ pass +n_vars = 0 + class Var(GenVar): def __init__(self): - pass + global n_vars + self.name = '%v' + str(n_vars) + n_vars += 1 + + def operand(self): + return 'int ' + self.name + + def operand2(self): + return self.name #repr? @@ -22,6 +33,12 @@ def __init__(self, value): self.value = value + def operand(self): + return 'int ' + str(self.value) + + def operand2(self): + return str(self.value) + @specialize.arg(1) def revealconst(self, T): if isinstance(T, lltype.Ptr): @@ -39,6 +56,12 @@ def __init__(self, addr): self.addr = addr + def operand(self): + return 'int* ' + str(llmemory.cast_adr_to_int(self.addr)) + + def operand2(self): + return str(llmemory.cast_adr_to_int(self.addr)) + @specialize.arg(1) def revealconst(self, T): if T is llmemory.Address: @@ -63,85 +86,81 @@ class FlexSwitch(CodeGenSwitch): - # - def __init__(self, rgenop): log('FlexSwitch.__init__') self.rgenop = rgenop - self.default_case_addr = 0 + #self.default_case_addr = 0 def initialize(self, builder, gv_exitswitch): - log('FlexSwitch.initialize') - mc = builder.mc - mc.MOV(eax, gv_exitswitch.operand(builder)) - self.saved_state = builder._save_state() - self._reserve(mc) + log('FlexSwitch.initialize TODO') + #mc = builder.mc + #mc.MOV(eax, gv_exitswitch.operand(builder)) + #self.saved_state = builder._save_state() + #self._reserve(mc) def _reserve(self, mc): - log('FlexSwitch._reserve') - RESERVED = 11*4+5 # XXX quite a lot for now :-/ - pos = mc.tell() - mc.UD2() - mc.write('\x00' * (RESERVED-1)) - self.nextfreepos = pos - self.endfreepos = pos + RESERVED + log('FlexSwitch._reserve TODO') + #RESERVED = 11*4+5 # XXX quite a lot for now :-/ + #pos = mc.tell() + #mc.UD2() + #mc.write('\x00' * (RESERVED-1)) + #self.nextfreepos = pos + #self.endfreepos = pos + RESERVED def _reserve_more(self): - log('FlexSwitch._reserve_more') - start = self.nextfreepos - end = self.endfreepos - newmc = self.rgenop.open_mc() - self._reserve(newmc) - self.rgenop.close_mc(newmc) - fullmc = InMemoryCodeBuilder(start, end) - fullmc.JMP(rel32(self.nextfreepos)) - fullmc.done() + log('FlexSwitch._reserve_more TODO') + #start = self.nextfreepos + #end = self.endfreepos + #newmc = self.rgenop.open_mc() + #self._reserve(newmc) + #self.rgenop.close_mc(newmc) + #fullmc = InMemoryCodeBuilder(start, end) + #fullmc.JMP(rel32(self.nextfreepos)) + #fullmc.done() def add_case(self, gv_case): - log('FlexSwitch.add_case') - rgenop = self.rgenop - targetbuilder = Builder._new_from_state(rgenop, self.saved_state) - target_addr = targetbuilder.mc.tell() - try: - self._add_case(gv_case, target_addr) - except CodeBlockOverflow: - self._reserve_more() - self._add_case(gv_case, target_addr) - return targetbuilder + log('FlexSwitch.add_case TODO') + #rgenop = self.rgenop + #targetbuilder = Builder._new_from_state(rgenop, self.saved_state) + #target_addr = targetbuilder.mc.tell() + #try: + # self._add_case(gv_case, target_addr) + #except CodeBlockOverflow: + # self._reserve_more() + # self._add_case(gv_case, target_addr) + #return targetbuilder def _add_case(self, gv_case, target_addr): - log('FlexSwitch._add_case') - start = self.nextfreepos - end = self.endfreepos - mc = InMemoryCodeBuilder(start, end) - mc.CMP(eax, gv_case.operand(None)) - mc.JE(rel32(target_addr)) - pos = mc.tell() - if self.default_case_addr: - mc.JMP(rel32(self.default_case_addr)) - else: - illegal_start = mc.tell() - mc.JMP(rel32(0)) - ud2_addr = mc.tell() - mc.UD2() - illegal_mc = InMemoryCodeBuilder(illegal_start, end) - illegal_mc.JMP(rel32(ud2_addr)) - mc.done() - self.nextfreepos = pos + log('FlexSwitch._add_case TODO') + #start = self.nextfreepos + #end = self.endfreepos + #mc = InMemoryCodeBuilder(start, end) + #mc.CMP(eax, gv_case.operand(None)) + #mc.JE(rel32(target_addr)) + #pos = mc.tell() + #if self.default_case_addr: + # mc.JMP(rel32(self.default_case_addr)) + #else: + # illegal_start = mc.tell() + # mc.JMP(rel32(0)) + # ud2_addr = mc.tell() + # mc.UD2() + # illegal_mc = InMemoryCodeBuilder(illegal_start, end) + # illegal_mc.JMP(rel32(ud2_addr)) + #mc.done() + #self.nextfreepos = pos def add_default(self): - log('FlexSwitch.add_default') - rgenop = self.rgenop - targetbuilder = Builder._new_from_state(rgenop, self.saved_state) - self.default_case_addr = targetbuilder.mc.tell() - start = self.nextfreepos - end = self.endfreepos - mc = InMemoryCodeBuilder(start, end) - mc.JMP(rel32(self.default_case_addr)) - mc.done() - return targetbuilder - - # + log('FlexSwitch.add_default TODO') + #rgenop = self.rgenop + #targetbuilder = Builder._new_from_state(rgenop, self.saved_state) + #self.default_case_addr = targetbuilder.mc.tell() + #start = self.nextfreepos + #end = self.endfreepos + #mc = InMemoryCodeBuilder(start, end) + #mc.JMP(rel32(self.default_case_addr)) + #mc.done() + #return targetbuilder class Builder(object): #changed baseclass from (GenBuilder) for better error messages @@ -156,20 +175,29 @@ def end(self): log('Builder.end') - pass + self.asm.append('}') + asm_string = '\n'.join(self.asm) + log(asm_string) + llvmjit.parse(asm_string) + function = llvmjit.getNamedFunction(self.rgenop.name) + entrypoint = llvmjit.getPointerToFunction(function) + self.rgenop.gv_entrypoint.value = entrypoint + #print self.rgenop.name, 'entrypoint', entrypoint + #print self.rgenop.gv_entrypoint, self.rgenop.gv_entrypoint.value def _write_prologue(self, sigtoken): log('Builder._write_prologue') numargs = sigtoken # for now - #self.mc.BREAKPOINT() - return [Var() for i in range(numargs)] + inputargs_gv = [Var() for i in range(numargs)] + self.asm.append('int %%%s(%s){' % ( + self.rgenop.name, ','.join([v.operand() for v in inputargs_gv]))) + return inputargs_gv def _close(self): log('Builder._close') - return - self.mc.done() - self.rgenop.close_mc(self.mc) - self.mc = None + #self.mc.done() + #self.rgenop.close_mc(self.mc) + #self.mc = None @specialize.arg(1) def genop1(self, opname, gv_arg): @@ -186,47 +214,45 @@ def op_int_add(self, gv_x, gv_y): log('Builder.op_int_add') gv_result = Var() + self.asm.append(" %s=add %s,%s" % (gv_result.name, gv_x.operand(), gv_y.operand2())) return gv_result - self.mc.MOV(eax, gv_x.operand(self)) - self.mc.ADD(eax, gv_y.operand(self)) - return self.returnvar(eax) + #self.mc.MOV(eax, gv_x.operand(self)) + #self.mc.ADD(eax, gv_y.operand(self)) + #return self.returnvar(eax) def enter_next_block(self, kinds, args_gv): - log('Builder.enter_next_block') - return - arg_positions = [] - seen = {} - for i in range(len(args_gv)): - gv = args_gv[i] - # turn constants into variables; also make copies of vars that - # are duplicate in args_gv - if not isinstance(gv, Var) or gv.stackpos in seen: - gv = args_gv[i] = self.returnvar(gv.operand(self)) - # remember the var's position in the stack - arg_positions.append(gv.stackpos) - seen[gv.stackpos] = None - return Label(self.mc.tell(), arg_positions, self.stackdepth) + log('Builder.enter_next_block TODO') + #arg_positions = [] + #seen = {} + #for i in range(len(args_gv)): + # gv = args_gv[i] + # # turn constants into variables; also make copies of vars that + # # are duplicate in args_gv + # if not isinstance(gv, Var) or gv.stackpos in seen: + # gv = args_gv[i] = self.returnvar(gv.operand(self)) + # # remember the var's position in the stack + # arg_positions.append(gv.stackpos) + # seen[gv.stackpos] = None + #return Label(self.mc.tell(), arg_positions, self.stackdepth) def finish_and_return(self, sigtoken, gv_returnvar): log('Builder.finish_and_return') - return - numargs = sigtoken # for now - initialstackdepth = numargs + 1 - self.mc.MOV(eax, gv_returnvar.operand(self)) - self.mc.ADD(esp, imm(WORD * (self.stackdepth - initialstackdepth))) - self.mc.RET() + self.asm.append(' ret ' + gv_returnvar.operand()) + #numargs = sigtoken # for now + #initialstackdepth = numargs + 1 + #self.mc.MOV(eax, gv_returnvar.operand(self)) + #self.mc.ADD(esp, imm(WORD * (self.stackdepth - initialstackdepth))) + #self.mc.RET() self._close() def finish_and_goto(self, outputargs_gv, target): - log('Builder.finish_and_goto') - return - remap_stack_layout(self, outputargs_gv, target) - self.mc.JMP(rel32(target.startaddr)) + log('Builder.finish_and_goto TODO') + #remap_stack_layout(self, outputargs_gv, target) + #self.mc.JMP(rel32(target.startaddr)) self._close() def flexswitch(self, gv_exitswitch): - log('Builder.flexswitch') - return + log('Builder.flexswitch TODO') result = FlexSwitch(self.rgenop) result.initialize(self, gv_exitswitch) self._close() @@ -254,11 +280,12 @@ def newgraph(self, sigtoken, name): log('RLLVMGenOp.newgraph') numargs = sigtoken # for now + self.name = name builder = self.openbuilder() #entrypoint = builder.asm.mc.tell() - entrypoint = 0 #XXX + self.gv_entrypoint = IntConst(0) inputargs_gv = builder._write_prologue(sigtoken) - return builder, IntConst(entrypoint), inputargs_gv + return builder, self.gv_entrypoint, inputargs_gv @specialize.genconst(1) def genconst(self, llvalue): #i386 version (ppc version is slightly different) Modified: pypy/dist/pypy/jit/codegen/llvm/test/test_llvmjit.py ============================================================================== --- pypy/dist/pypy/jit/codegen/llvm/test/test_llvmjit.py (original) +++ pypy/dist/pypy/jit/codegen/llvm/test/test_llvmjit.py Tue Dec 5 20:43:53 2006 @@ -132,6 +132,12 @@ llvmjit.restart() assert execute(llsquare, 'square', 4) == 4 * 4 +def test_execute_with_ctypes(): + py.test.skip('TODO: implement execute with ctypes thru real pointer to function') + llvmjit.restart() + #should use function.getPointerToFunction + assert execute(llsquare, 'square', 4) == 4 * 4 + def test_execute_nothing(): llvmjit.restart() assert llvmjit.execute(None, 4) == -1 #-1 == no function supplied Modified: pypy/dist/pypy/jit/codegen/llvm/test/test_rgenop.py ============================================================================== --- pypy/dist/pypy/jit/codegen/llvm/test/test_rgenop.py (original) +++ pypy/dist/pypy/jit/codegen/llvm/test/test_rgenop.py Tue Dec 5 20:43:53 2006 @@ -1,9 +1,31 @@ import py from pypy.jit.codegen.llvm.rgenop import RLLVMGenOp from pypy.jit.codegen.test.rgenop_tests import AbstractRGenOpTests +from pypy.rpython.lltypesystem import lltype +from ctypes import c_void_p, cast, CFUNCTYPE, c_int -py.test.skip("WIP") +FUNC = lltype.FuncType([lltype.Signed], lltype.Signed) + +def make_adder(rgenop, n): + # 'return x+n' + sigtoken = rgenop.sigToken(FUNC) + builder, gv_add_one, [gv_x] = rgenop.newgraph(sigtoken, "adder") + #note: entrypoint (gv_add_one.value) gets updated by builder.end() (don't use before that!) + gv_result = builder.genop2("int_add", gv_x, rgenop.genconst(n)) + builder.finish_and_return(sigtoken, gv_result) + builder.end() + return gv_add_one + +def test_adder_direct(): + rgenop = RLLVMGenOp() + gv_add_5 = make_adder(rgenop, 5) + fnptr = cast(c_void_p(gv_add_5.value), CFUNCTYPE(c_int, c_int)) + #fnptr = gv_add_5.revealconst(lltype.Ptr(FUNC)) + res = fnptr(37) + assert res == 42 + + +#class TestRLLVMGenop(AbstractRGenOpTests): +# RGenOp = RLLVMGenOp -class TestRLLVMGenop(AbstractRGenOpTests): - RGenOp = RLLVMGenOp From fijal at codespeak.net Tue Dec 5 21:09:14 2006 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 5 Dec 2006 21:09:14 +0100 (CET) Subject: [pypy-svn] r35335 - pypy/dist/pypy/translator/js/examples Message-ID: <20061205200914.AC8A01007C@code0.codespeak.net> Author: fijal Date: Tue Dec 5 21:09:09 2006 New Revision: 35335 Modified: pypy/dist/pypy/translator/js/examples/server.py Log: killed js_optiondescr reference Modified: pypy/dist/pypy/translator/js/examples/server.py ============================================================================== --- pypy/dist/pypy/translator/js/examples/server.py (original) +++ pypy/dist/pypy/translator/js/examples/server.py Tue Dec 5 21:09:09 2006 @@ -29,10 +29,9 @@ from pypy.rpython.ootypesystem.bltregistry import MethodDesc, BasicExternal,\ described -from pypy.translator.js.main import rpython2javascript, js_optiondescr +from pypy.translator.js.main import rpython2javascript from pypy.translator.js import commproxy -js_optiondescr.debug_transform = False commproxy.USE_MOCHIKIT = True class ExportedMethods(BasicExternal): From fijal at codespeak.net Tue Dec 5 21:09:27 2006 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 5 Dec 2006 21:09:27 +0100 (CET) Subject: [pypy-svn] r35336 - pypy/dist/pypy/translator/js Message-ID: <20061205200927.ECB4910078@code0.codespeak.net> Author: fijal Date: Tue Dec 5 21:09:25 2006 New Revision: 35336 Modified: pypy/dist/pypy/translator/js/main.py Log: typo Modified: pypy/dist/pypy/translator/js/main.py ============================================================================== --- pypy/dist/pypy/translator/js/main.py (original) +++ pypy/dist/pypy/translator/js/main.py Tue Dec 5 21:09:25 2006 @@ -114,7 +114,7 @@ def rpython2javascript(mod, function_names, jsconfig=None, use_pdb=True): if jsconfig is None: - jsconfig = Config(js_optiondescr ) + jsconfig = Config(js_optiondescr) if use_pdb: jsconfig.use_pdb = True module_name = mod.__name__ From arigo at codespeak.net Tue Dec 5 21:50:42 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 5 Dec 2006 21:50:42 +0100 (CET) Subject: [pypy-svn] r35338 - in pypy/dist/pypy: annotation rpython rpython/test Message-ID: <20061205205042.828C710071@code0.codespeak.net> Author: arigo Date: Tue Dec 5 21:50:39 2006 New Revision: 35338 Modified: pypy/dist/pypy/annotation/annrpython.py pypy/dist/pypy/rpython/robject.py pypy/dist/pypy/rpython/test/test_exception.py Log: (pedronis, arigo) Two more test cases and fixes for annotating exception blocks. Urgh. Modified: pypy/dist/pypy/annotation/annrpython.py ============================================================================== --- pypy/dist/pypy/annotation/annrpython.py (original) +++ pypy/dist/pypy/annotation/annrpython.py Tue Dec 5 21:50:39 2006 @@ -614,7 +614,6 @@ candidates = [c for c in candidates if c not in covered] for link in exits: - self.links_followed[link] = True import types in_except_block = False @@ -695,7 +694,12 @@ if in_except_block: last_exception_object.is_type_of = last_exc_value_vars + if annmodel.s_ImpossibleValue in cells: + continue # ignore links that try to pass impossible values + + self.links_followed[link] = True self.addpendingblock(graph, link.target, cells) + if block in self.notify: # reflow from certain positions when this block is done for callback in self.notify[block]: Modified: pypy/dist/pypy/rpython/robject.py ============================================================================== --- pypy/dist/pypy/rpython/robject.py (original) +++ pypy/dist/pypy/rpython/robject.py Tue Dec 5 21:50:39 2006 @@ -9,10 +9,10 @@ class __extend__(annmodel.SomeObject): def rtyper_makerepr(self, rtyper): - if self.is_constant(): - return constpyobj_repr if self.knowntype is type: return rclass.get_type_repr(rtyper) + elif self.is_constant(): + return constpyobj_repr else: return pyobj_repr def rtyper_makekey(self): Modified: pypy/dist/pypy/rpython/test/test_exception.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_exception.py (original) +++ pypy/dist/pypy/rpython/test/test_exception.py Tue Dec 5 21:50:39 2006 @@ -1,6 +1,8 @@ +import py from pypy.translator.translator import TranslationContext from pypy.rpython.lltypesystem.lltype import * from pypy.rpython.test.tool import BaseRtypingTest, LLRtypeMixin, OORtypeMixin +from pypy.rpython.llinterp import LLException class MyException(Exception): pass @@ -80,6 +82,38 @@ res = self.interpret(f, [7]) assert res is None + def test_raise_and_catch_other(self): + class BytecodeCorruption(Exception): + pass + class OperationError(Exception): + def __init__(self, a): + self.a = a + def f(next_instr): + if next_instr < 7: + raise OperationError(next_instr) + try: + raise BytecodeCorruption() + except OperationError, operr: + next_instr -= operr.a + py.test.raises(LLException, self.interpret, f, [10]) + + def test_raise_prebuilt_and_catch_other(self): + class BytecodeCorruption(Exception): + pass + class OperationError(Exception): + def __init__(self, a): + self.a = a + bcerr = BytecodeCorruption() + def f(next_instr): + if next_instr < 7: + raise OperationError(next_instr) + try: + raise bcerr + except OperationError, operr: + next_instr -= operr.a + py.test.raises(LLException, self.interpret, f, [10]) + + class TestLLtype(BaseTestException, LLRtypeMixin): pass From arigo at codespeak.net Tue Dec 5 21:53:58 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 5 Dec 2006 21:53:58 +0100 (CET) Subject: [pypy-svn] r35339 - in pypy/branch/jit-real-world/pypy: annotation rpython rpython/test Message-ID: <20061205205358.E8BF010077@code0.codespeak.net> Author: arigo Date: Tue Dec 5 21:53:56 2006 New Revision: 35339 Modified: pypy/branch/jit-real-world/pypy/annotation/annrpython.py pypy/branch/jit-real-world/pypy/rpython/robject.py pypy/branch/jit-real-world/pypy/rpython/test/test_exception.py Log: svn merge -r35324:35338 http://codespeak.net/svn/pypy/dist/pypy/rpython svn merge -r35324:35338 http://codespeak.net/svn/pypy/dist/pypy/annotation Modified: pypy/branch/jit-real-world/pypy/annotation/annrpython.py ============================================================================== --- pypy/branch/jit-real-world/pypy/annotation/annrpython.py (original) +++ pypy/branch/jit-real-world/pypy/annotation/annrpython.py Tue Dec 5 21:53:56 2006 @@ -614,7 +614,6 @@ candidates = [c for c in candidates if c not in covered] for link in exits: - self.links_followed[link] = True import types in_except_block = False @@ -695,7 +694,12 @@ if in_except_block: last_exception_object.is_type_of = last_exc_value_vars + if annmodel.s_ImpossibleValue in cells: + continue # ignore links that try to pass impossible values + + self.links_followed[link] = True self.addpendingblock(graph, link.target, cells) + if block in self.notify: # reflow from certain positions when this block is done for callback in self.notify[block]: Modified: pypy/branch/jit-real-world/pypy/rpython/robject.py ============================================================================== --- pypy/branch/jit-real-world/pypy/rpython/robject.py (original) +++ pypy/branch/jit-real-world/pypy/rpython/robject.py Tue Dec 5 21:53:56 2006 @@ -9,10 +9,10 @@ class __extend__(annmodel.SomeObject): def rtyper_makerepr(self, rtyper): - if self.is_constant(): - return constpyobj_repr if self.knowntype is type: return rclass.get_type_repr(rtyper) + elif self.is_constant(): + return constpyobj_repr else: return pyobj_repr def rtyper_makekey(self): Modified: pypy/branch/jit-real-world/pypy/rpython/test/test_exception.py ============================================================================== --- pypy/branch/jit-real-world/pypy/rpython/test/test_exception.py (original) +++ pypy/branch/jit-real-world/pypy/rpython/test/test_exception.py Tue Dec 5 21:53:56 2006 @@ -1,6 +1,8 @@ +import py from pypy.translator.translator import TranslationContext from pypy.rpython.lltypesystem.lltype import * from pypy.rpython.test.tool import BaseRtypingTest, LLRtypeMixin, OORtypeMixin +from pypy.rpython.llinterp import LLException class MyException(Exception): pass @@ -80,6 +82,38 @@ res = self.interpret(f, [7]) assert res is None + def test_raise_and_catch_other(self): + class BytecodeCorruption(Exception): + pass + class OperationError(Exception): + def __init__(self, a): + self.a = a + def f(next_instr): + if next_instr < 7: + raise OperationError(next_instr) + try: + raise BytecodeCorruption() + except OperationError, operr: + next_instr -= operr.a + py.test.raises(LLException, self.interpret, f, [10]) + + def test_raise_prebuilt_and_catch_other(self): + class BytecodeCorruption(Exception): + pass + class OperationError(Exception): + def __init__(self, a): + self.a = a + bcerr = BytecodeCorruption() + def f(next_instr): + if next_instr < 7: + raise OperationError(next_instr) + try: + raise bcerr + except OperationError, operr: + next_instr -= operr.a + py.test.raises(LLException, self.interpret, f, [10]) + + class TestLLtype(BaseTestException, LLRtypeMixin): pass From arigo at codespeak.net Tue Dec 5 21:55:49 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 5 Dec 2006 21:55:49 +0100 (CET) Subject: [pypy-svn] r35340 - pypy/dist/pypy/translator/tool Message-ID: <20061205205549.B3AAC10079@code0.codespeak.net> Author: arigo Date: Tue Dec 5 21:55:44 2006 New Revision: 35340 Modified: pypy/dist/pypy/translator/tool/graphpage.py Log: Avoid a crash in pdbplus with 'callg non_annotated_function'. Modified: pypy/dist/pypy/translator/tool/graphpage.py ============================================================================== --- pypy/dist/pypy/translator/tool/graphpage.py (original) +++ pypy/dist/pypy/translator/tool/graphpage.py Tue Dec 5 21:55:44 2006 @@ -375,7 +375,10 @@ that means just including direct callers and callees""" def graph_name(self, centers): - return 'LCG_%s' % nameof(centers[0]) + if centers: + return 'LCG_%s' % nameof(centers[0]) + else: + return 'EMPTY' def do_compute(self, dotgen, centers): centers = dict.fromkeys(centers) From arigo at codespeak.net Tue Dec 5 22:21:11 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 5 Dec 2006 22:21:11 +0100 (CET) Subject: [pypy-svn] r35343 - pypy/dist/pypy/annotation Message-ID: <20061205212111.47C2C10075@code0.codespeak.net> Author: arigo Date: Tue Dec 5 22:21:09 2006 New Revision: 35343 Modified: pypy/dist/pypy/annotation/annrpython.py Log: (pedronis, arigo) Trying to make pypy translatable again... Modified: pypy/dist/pypy/annotation/annrpython.py ============================================================================== --- pypy/dist/pypy/annotation/annrpython.py (original) +++ pypy/dist/pypy/annotation/annrpython.py Tue Dec 5 22:21:09 2006 @@ -645,6 +645,7 @@ last_exc_value_vars = [] in_except_block = True + ignore_link = False cells = [] renaming = {} for a,v in zip(link.args,link.target.inputargs): @@ -662,6 +663,9 @@ if (link.exitcase, a) in knowntypedata: knownvarvalue = knowntypedata[(link.exitcase, a)] cell = pair(cell, knownvarvalue).improve() + # ignore links that try to pass impossible values + if cell == annmodel.s_ImpossibleValue: + ignore_link = True if hasattr(cell,'is_type_of'): renamed_is_type_of = [] @@ -691,12 +695,12 @@ cells.append(cell) + if ignore_link: + continue + if in_except_block: last_exception_object.is_type_of = last_exc_value_vars - if annmodel.s_ImpossibleValue in cells: - continue # ignore links that try to pass impossible values - self.links_followed[link] = True self.addpendingblock(graph, link.target, cells) From guido at codespeak.net Tue Dec 5 22:52:07 2006 From: guido at codespeak.net (guido at codespeak.net) Date: Tue, 5 Dec 2006 22:52:07 +0100 (CET) Subject: [pypy-svn] r35345 - pypy/dist/pypy/translator/js/modules Message-ID: <20061205215207.48A4910071@code0.codespeak.net> Author: guido Date: Tue Dec 5 22:52:06 2006 New Revision: 35345 Modified: pypy/dist/pypy/translator/js/modules/dom.py Log: Removed some useless __init__s. 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 Dec 5 22:52:06 2006 @@ -87,6 +87,7 @@ def __setattr__(self, name, value): """set an attribute on the wrapped node""" + print dir(self) if name in dir(self): return super(Node, self).__setattr__(name, value) if name not in self._fields: @@ -128,9 +129,6 @@ nodeType = 1 style = None - def __init__(self, node=None): - super(Element, self).__init__(node) - def _style(self): style = getattr(self._original, '_style', None) if style is not None: @@ -181,10 +179,6 @@ class Document(Node): nodeType = 9 - def __init__(self, docnode=None): - super(Document, self).__init__(docnode) - self._original = docnode - def createEvent(self, group=''): """create an event From fijal at codespeak.net Tue Dec 5 22:57:24 2006 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 5 Dec 2006 22:57:24 +0100 (CET) Subject: [pypy-svn] r35346 - pypy/dist/pypy/translator/js Message-ID: <20061205215724.92CBD10079@code0.codespeak.net> Author: fijal Date: Tue Dec 5 22:57:22 2006 New Revision: 35346 Modified: pypy/dist/pypy/translator/js/tester.py Log: Relax a bit... Modified: pypy/dist/pypy/translator/js/tester.py ============================================================================== --- pypy/dist/pypy/translator/js/tester.py (original) +++ pypy/dist/pypy/translator/js/tester.py Tue Dec 5 22:57:22 2006 @@ -14,6 +14,9 @@ # otherwise.... def wrapper(*args, **kwargs): args = list(args) + # do this only if last arg is callable + if not (len(args) > 0 and callable(args[-1])): + return val(*args, **kwargs) callback = args.pop() res = val(*args, **kwargs) if not hasattr(self, '__callbacks'): From guido at codespeak.net Tue Dec 5 23:39:50 2006 From: guido at codespeak.net (guido at codespeak.net) Date: Tue, 5 Dec 2006 23:39:50 +0100 (CET) Subject: [pypy-svn] r35348 - pypy/dist/pypy/translator/js/modules Message-ID: <20061205223950.BA27B10077@code0.codespeak.net> Author: guido Date: Tue Dec 5 23:39:47 2006 New Revision: 35348 Modified: pypy/dist/pypy/translator/js/modules/dom.py Log: Added (dummy) Element.scrollIntoView() method. 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 Dec 5 23:39:47 2006 @@ -167,6 +167,9 @@ innerHTML = property(_get_innerHTML, _set_innerHTML) + def scrollIntoView(self): + pass + class Attribute(Node): nodeType = 2 From arigo at codespeak.net Wed Dec 6 01:08:07 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 6 Dec 2006 01:08:07 +0100 (CET) Subject: [pypy-svn] r35350 - pypy/dist/pypy/rpython Message-ID: <20061206000807.ABC1010071@code0.codespeak.net> Author: arigo Date: Wed Dec 6 01:08:00 2006 New Revision: 35350 Modified: pypy/dist/pypy/rpython/robject.py Log: (pedronis, arigo) Fix buggy fix. See translator/test/test_extension. Modified: pypy/dist/pypy/rpython/robject.py ============================================================================== --- pypy/dist/pypy/rpython/robject.py (original) +++ pypy/dist/pypy/rpython/robject.py Wed Dec 6 01:08:00 2006 @@ -9,19 +9,25 @@ class __extend__(annmodel.SomeObject): def rtyper_makerepr(self, rtyper): - if self.knowntype is type: + kind = getkind(self) + if kind == "type": return rclass.get_type_repr(rtyper) - elif self.is_constant(): + elif kind == "const": return constpyobj_repr else: return pyobj_repr def rtyper_makekey(self): - if self.is_constant(): - return self.__class__, "const" - if self.knowntype is type: - return self.__class__, "type" - else: - return self.__class__, "pyobj" + return self.__class__, getkind(self) + +def getkind(s_obj): + if s_obj.is_constant(): + if getattr(s_obj.const, '__module__', None) == '__builtin__': + return "const" + if s_obj.knowntype is type: + return "type" + if s_obj.is_constant(): + return "const" + return "pyobj" class PyObjRepr(Repr): From arigo at codespeak.net Wed Dec 6 03:02:55 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 6 Dec 2006 03:02:55 +0100 (CET) Subject: [pypy-svn] r35353 - in pypy/dist/pypy: annotation rpython/test Message-ID: <20061206020255.249201006F@code0.codespeak.net> Author: arigo Date: Wed Dec 6 03:02:32 2006 New Revision: 35353 Modified: pypy/dist/pypy/annotation/binaryop.py pypy/dist/pypy/rpython/test/test_rpbc.py Log: (pedronis, arigo) Yet another rpbc corner case. Modified: pypy/dist/pypy/annotation/binaryop.py ============================================================================== --- pypy/dist/pypy/annotation/binaryop.py (original) +++ pypy/dist/pypy/annotation/binaryop.py Wed Dec 6 03:02:32 2006 @@ -630,11 +630,23 @@ return SomeBuiltin(bltn1.analyser, s_self, methodname=bltn1.methodname) class __extend__(pairtype(SomePBC, SomePBC)): + def union((pbc1, pbc2)): d = pbc1.descriptions.copy() d.update(pbc2.descriptions) return SomePBC(d, can_be_None = pbc1.can_be_None or pbc2.can_be_None) + def is_((obj1, obj2)): + thistype = pairtype(SomePBC, SomePBC) + s = super(thistype, pair(obj1, obj2)).is_() + if not s.is_constant(): + for desc in obj1.descriptions: + if desc in obj2.descriptions: + break + else: + s.const = False # no common desc in the two sets + return s + class __extend__(pairtype(SomeImpossibleValue, SomeObject)): def union((imp1, obj2)): return obj2 Modified: pypy/dist/pypy/rpython/test/test_rpbc.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_rpbc.py (original) +++ pypy/dist/pypy/rpython/test/test_rpbc.py Wed Dec 6 03:02:32 2006 @@ -1477,6 +1477,20 @@ res = self.interpret(f, [5]) assert res == 123 + def test_is_among_functions(self): + def g1(): pass + def g2(): pass + def g3(): pass + def f(n): + if n > 5: + g = g2 + else: + g = g1 + g() + g3() + return g is g3 + res = self.interpret(f, [2]) + assert res == False # We don't care about the following test_hlinvoke tests working on # ootype. Maybe later. This kind of thing is only used in rdict From arigo at codespeak.net Wed Dec 6 03:03:29 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 6 Dec 2006 03:03:29 +0100 (CET) Subject: [pypy-svn] r35354 - pypy/dist/pypy/rpython Message-ID: <20061206020329.9FB0910078@code0.codespeak.net> Author: arigo Date: Wed Dec 6 03:03:17 2006 New Revision: 35354 Modified: pypy/dist/pypy/rpython/rtyper.py Log: Fix very very very old code. Modified: pypy/dist/pypy/rpython/rtyper.py ============================================================================== --- pypy/dist/pypy/rpython/rtyper.py (original) +++ pypy/dist/pypy/rpython/rtyper.py Wed Dec 6 03:03:17 2006 @@ -243,12 +243,8 @@ bc += 1 continue block, position = err.where - func = self.annotator.annotated.get(block, None) - if func: - func = "(%s:%s)" %(func.__module__ or '?', func.__name__) - else: - func = "(?:?)" - errmsg = ("TyperError-%d: %s" % (c, func) + + graph = self.annotator.annotated.get(block, None) + errmsg = ("TyperError-%d: %s\n" % (c, graph) + str(err) + "\n") if to_log: From arigo at codespeak.net Wed Dec 6 03:05:27 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 6 Dec 2006 03:05:27 +0100 (CET) Subject: [pypy-svn] r35355 - pypy/dist/pypy/rlib Message-ID: <20061206020527.DCE2A10071@code0.codespeak.net> Author: arigo Date: Wed Dec 6 03:05:08 2006 New Revision: 35355 Modified: pypy/dist/pypy/rlib/rarithmetic.py Log: Another exception_cannot_occur(). Modified: pypy/dist/pypy/rlib/rarithmetic.py ============================================================================== --- pypy/dist/pypy/rlib/rarithmetic.py (original) +++ pypy/dist/pypy/rlib/rarithmetic.py Wed Dec 6 03:05:08 2006 @@ -313,6 +313,7 @@ def specialize_call(self, hop): v_result, = hop.inputargs(hop.r_result.lowleveltype) + hop.exception_cannot_occur() return v_result return int_type From arigo at codespeak.net Wed Dec 6 03:06:47 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 6 Dec 2006 03:06:47 +0100 (CET) Subject: [pypy-svn] r35356 - pypy/branch/jit-real-world/pypy/jit/timeshifter Message-ID: <20061206020647.F1F2610075@code0.codespeak.net> Author: arigo Date: Wed Dec 6 03:06:36 2006 New Revision: 35356 Modified: pypy/branch/jit-real-world/pypy/jit/timeshifter/transform.py Log: (pedronis, arigo) Fix the graph->tsgraph mapping, along the lines of "how could it ever work". Modified: pypy/branch/jit-real-world/pypy/jit/timeshifter/transform.py ============================================================================== --- pypy/branch/jit-real-world/pypy/jit/timeshifter/transform.py (original) +++ pypy/branch/jit-real-world/pypy/jit/timeshifter/transform.py Wed Dec 6 03:06:36 2006 @@ -115,11 +115,15 @@ c = 'red' return c - def timeshifted_graph_of(self, graph, args_v): + def timeshifted_graph_of(self, graph, args_v, v_result): bk = self.hannotator.bookkeeper args_hs = [self.hannotator.binding(v) for v in args_v] - # fixed is always false here - specialization_key = bk.specialization_key(False, args_hs) + hs_result = self.hannotator.binding(v_result) + if isinstance(hs_result, hintmodel.SomeLLAbstractConstant): + fixed = hs_result.is_fixed() + else: + fixed = False + specialization_key = bk.specialization_key(fixed, args_hs) tsgraph = bk.get_graph_by_key(graph, specialization_key) self.tsgraphs_seen.append(tsgraph) return tsgraph @@ -451,7 +455,7 @@ if not self.hannotator.policy.look_inside_graphs(graphs): return # cannot follow this call for graph in graphs: - tsgraph = self.timeshifted_graph_of(graph, args_v) + tsgraph = self.timeshifted_graph_of(graph, args_v, spaceop.result) yield graph, tsgraph def guess_call_kind(self, spaceop): From arigo at codespeak.net Wed Dec 6 03:08:17 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 6 Dec 2006 03:08:17 +0100 (CET) Subject: [pypy-svn] r35357 - in pypy/branch/jit-real-world/pypy: jit/goal module/pypyjit Message-ID: <20061206020817.C105610071@code0.codespeak.net> Author: arigo Date: Wed Dec 6 03:08:02 2006 New Revision: 35357 Added: pypy/branch/jit-real-world/pypy/module/pypyjit/ (props changed) pypy/branch/jit-real-world/pypy/module/pypyjit/__init__.py (contents, props changed) pypy/branch/jit-real-world/pypy/module/pypyjit/interp_jit.py (contents, props changed) Modified: pypy/branch/jit-real-world/pypy/jit/goal/jitstep.py pypy/branch/jit-real-world/pypy/jit/goal/targetjit.py Log: A module 'pypyjit', enabled by the targetjit. See the docstring of interp_jit for the purpose. Modified: pypy/branch/jit-real-world/pypy/jit/goal/jitstep.py ============================================================================== --- pypy/branch/jit-real-world/pypy/jit/goal/jitstep.py (original) +++ pypy/branch/jit-real-world/pypy/jit/goal/jitstep.py Wed Dec 6 03:08:02 2006 @@ -1,12 +1,11 @@ -from pypy.interpreter.pyframe import PyFrame +from pypy.module.pypyjit.interp_jit import PORTAL from pypy.objspace.flow.model import checkgraph from pypy.translator.translator import graphof from pypy.jit.hintannotator.annotator import HintAnnotator, HintAnnotatorPolicy from pypy.jit.hintannotator.model import OriginFlags, SomeLLAbstractConstant -PORTAL = PyFrame.dispatch_bytecode.im_func -#from pypy.jit.goal.x import evaluate as PORTAL +PORTAL = getattr(PORTAL, 'im_func', PORTAL) class PyPyHintAnnotatorPolicy(HintAnnotatorPolicy): Modified: pypy/branch/jit-real-world/pypy/jit/goal/targetjit.py ============================================================================== --- pypy/branch/jit-real-world/pypy/jit/goal/targetjit.py (original) +++ pypy/branch/jit-real-world/pypy/jit/goal/targetjit.py Wed Dec 6 03:08:02 2006 @@ -34,6 +34,7 @@ # return main, None def handle_config(self, config): + config.objspace.usemodules.pypyjit = True config.translation.backendopt.inline_threshold = 0 config.translation.backendopt.merge_if_blocks = False config.translation.fork_before = 'hintannotate' Added: pypy/branch/jit-real-world/pypy/module/pypyjit/__init__.py ============================================================================== --- (empty file) +++ pypy/branch/jit-real-world/pypy/module/pypyjit/__init__.py Wed Dec 6 03:08:02 2006 @@ -0,0 +1,13 @@ +from pypy.interpreter.mixedmodule import MixedModule + +class Module(MixedModule): + appleveldefs = { + } + + interpleveldefs = { + 'enable': 'interp_jit.enable', + } + + def setup_after_space_initialization(self): + # force the setup() to run early + import pypy.module.pypyjit.interp_jit Added: pypy/branch/jit-real-world/pypy/module/pypyjit/interp_jit.py ============================================================================== --- (empty file) +++ pypy/branch/jit-real-world/pypy/module/pypyjit/interp_jit.py Wed Dec 6 03:08:02 2006 @@ -0,0 +1,79 @@ +"""This is not the JIT :-) + +The pypyjit module helpers set the 'jit_enable' flag on code objects. +The code below makes two identical copies of the interpreter's main +loop, and the flag controls which of them is used. One of them +(dispatch_jit) is transformed to become a JIT by code elsewhere: +pypy/jit/* +""" +import py +from pypy.interpreter.pycode import PyCode +from pypy.interpreter.pyframe import PyFrame +from pypy.tool.sourcetools import func_with_new_name + + +PyCode.jit_enable = False # new default attribute +super_dispatch = PyFrame.dispatch +super_dispatch_bytecode = PyFrame.dispatch_bytecode + + +def setup(): + # create dispatch_jit() as a copy of dispatch() in which + # dispatch_bytecode() has been manually inlined. + # Do this with py.code.Source manipulations for now. + src = py.code.Source(super_dispatch) + CALL_SITE = 'return self.dispatch_bytecode(co_code, next_instr, ec)' + for i, line in enumerate(src): + if line.strip() == CALL_SITE: + break + else: + raise Exception("fix me! call to dispatch_bytecode() not found") + + indent = line[:line.index(CALL_SITE)] + + src2 = py.code.Source(PyFrame.dispatch_bytecode) + hdr = src2[0].strip() + assert hdr == 'def dispatch_bytecode(self, co_code, next_instr, ec):' + src2 = src2[1:].deindent().indent(indent) + + src3 = py.code.Source('%s\n%s\n%s\n' % (src[:i], src2, src[i+1:])) + #print src3 + d = {} + exec src3.compile() in super_dispatch.func_globals, d + PyFrame.dispatch_jit = func_with_new_name(d['dispatch'], 'dispatch_jit') + + class __extend__(PyFrame): + + def dispatch(self, co_code, next_instr, ec): + if self.pycode.jit_enable: + return self.dispatch_jit(co_code, next_instr, ec) + else: + return super_dispatch(self, co_code, next_instr, ec) + + return PyFrame.dispatch_jit + +def setup2(): + # TEMPORARY: only patches dispatch_bytecode. + PyFrame.dispatch_jit = func_with_new_name( + PyFrame.dispatch_bytecode.im_func, 'dispatch_jit') + + class __extend__(PyFrame): + + def dispatch_bytecode(self, co_code, next_instr, ec): + if self.pycode.jit_enable: + print "jitting:", self.pycode.co_name + return self.dispatch_jit(co_code, next_instr, ec) + else: + return super_dispatch_bytecode(self, co_code, next_instr, ec) + + return PyFrame.dispatch_bytecode + +PORTAL = setup2() + +# ____________________________________________________________ +# +# Public interface + +def enable(space, w_code, w_enabled=True): + code = space.interp_w(PyCode, w_code) + code.jit_enable = space.is_true(w_enabled) From arigo at codespeak.net Wed Dec 6 03:09:26 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 6 Dec 2006 03:09:26 +0100 (CET) Subject: [pypy-svn] r35358 - pypy/dist/pypy/rlib Message-ID: <20061206020926.6A4EB10077@code0.codespeak.net> Author: arigo Date: Wed Dec 6 03:09:11 2006 New Revision: 35358 Modified: pypy/dist/pypy/rlib/ros.py Log: Add forced args to ros, to be able to use it in the JIT. Modified: pypy/dist/pypy/rlib/ros.py ============================================================================== --- pypy/dist/pypy/rlib/ros.py (original) +++ pypy/dist/pypy/rlib/ros.py Wed Dec 6 03:09:11 2006 @@ -8,6 +8,7 @@ # we fake it with the real one name, value = name_eq_value.split('=', 1) os.putenv(name, value) +putenv._annenforceargs_ = (str,) _initial_items = os.environ.items() @@ -29,6 +30,7 @@ return value idx += 1 return None +getenv._annenforceargs_ = (str,) class DIR(object): @@ -49,3 +51,4 @@ def opendir(dirname): return DIR(dirname) +opendir._annenforceargs_ = (str,) From arigo at codespeak.net Wed Dec 6 03:11:03 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 6 Dec 2006 03:11:03 +0100 (CET) Subject: [pypy-svn] r35359 - pypy/dist/pypy/translator Message-ID: <20061206021103.AA1781007B@code0.codespeak.net> Author: arigo Date: Wed Dec 6 03:10:45 2006 New Revision: 35359 Modified: pypy/dist/pypy/translator/interactive.py Log: (pedronis, arigo) Reorder the building of the entry point graph, so that a "simplifying=False" flag can be taken into account. Modified: pypy/dist/pypy/translator/interactive.py ============================================================================== --- pypy/dist/pypy/translator/interactive.py (original) +++ pypy/dist/pypy/translator/interactive.py Wed Dec 6 03:10:45 2006 @@ -17,9 +17,6 @@ self.entry_point = entry_point self.context = TranslationContext(config=self.config) - # for t.view() to work just after construction - graph = self.context.buildflowgraph(entry_point) - self.context._prebuilt_graphs[entry_point] = graph # hook into driver events driver_own_event = self.driver._event @@ -30,6 +27,9 @@ self.driver_setup = False self.update_options(argtypes, kwds) + # for t.view() to work just after construction + graph = self.context.buildflowgraph(entry_point) + self.context._prebuilt_graphs[entry_point] = graph def view(self): self.context.view() From arigo at codespeak.net Wed Dec 6 03:12:23 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 6 Dec 2006 03:12:23 +0100 (CET) Subject: [pypy-svn] r35360 - pypy/dist/pypy/rpython Message-ID: <20061206021223.BC4BA1007B@code0.codespeak.net> Author: arigo Date: Wed Dec 6 03:12:04 2006 New Revision: 35360 Modified: pypy/dist/pypy/rpython/raddress.py pypy/dist/pypy/rpython/rptr.py Log: (pedronis, arigo) Another ll_str, to support str(address). Modified: pypy/dist/pypy/rpython/raddress.py ============================================================================== --- pypy/dist/pypy/rpython/raddress.py (original) +++ pypy/dist/pypy/rpython/raddress.py Wed Dec 6 03:12:04 2006 @@ -7,6 +7,7 @@ from pypy.rpython.rmodel import Repr, IntegerRepr from pypy.rpython.rptr import PtrRepr from pypy.rpython.lltypesystem import lltype +from pypy.rlib.rarithmetic import r_uint class __extend__(annmodel.SomeAddress): def rtyper_makerepr(self, rtyper): @@ -36,6 +37,11 @@ assert not isinstance(value, _address) return value + def ll_str(self, a): + from pypy.rpython.lltypesystem.rstr import ll_str + id = cast_adr_to_int(a) + return ll_str.ll_int2hex(r_uint(id), True) + def rtype_getattr(self, hop): v_access = hop.inputarg(address_repr, 0) return v_access Modified: pypy/dist/pypy/rpython/rptr.py ============================================================================== --- pypy/dist/pypy/rpython/rptr.py (original) +++ pypy/dist/pypy/rpython/rptr.py Wed Dec 6 03:12:04 2006 @@ -27,7 +27,7 @@ self.lowleveltype = ptrtype def ll_str(self, p): - from pypy.rpython.lltypesystem.rstr import LLHelpers, ll_str + from pypy.rpython.lltypesystem.rstr import ll_str id = lltype.cast_ptr_to_int(p) return ll_str.ll_int2hex(r_uint(id), True) From arigo at codespeak.net Wed Dec 6 03:14:34 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 6 Dec 2006 03:14:34 +0100 (CET) Subject: [pypy-svn] r35361 - in pypy/dist/pypy/annotation: . test Message-ID: <20061206021434.64BC010082@code0.codespeak.net> Author: arigo Date: Wed Dec 6 03:13:50 2006 New Revision: 35361 Modified: pypy/dist/pypy/annotation/description.py pypy/dist/pypy/annotation/test/test_annrpython.py Log: Oups! This should have gone together with, or before, r35358. Modified: pypy/dist/pypy/annotation/description.py ============================================================================== --- pypy/dist/pypy/annotation/description.py (original) +++ pypy/dist/pypy/annotation/description.py Wed Dec 6 03:13:50 2006 @@ -254,6 +254,10 @@ self.specializer = policy.get_specializer(tag) enforceargs = getattr(self.pyobj, '_annenforceargs_', None) if enforceargs: + if not callable(enforceargs): + from pypy.annotation.policy import Sig + enforceargs = Sig(*enforceargs) + self.pyobj._annenforceargs_ = enforceargs enforceargs(self, inputcells) # can modify inputcells in-place return self.specializer(self, inputcells) Modified: pypy/dist/pypy/annotation/test/test_annrpython.py ============================================================================== --- pypy/dist/pypy/annotation/test/test_annrpython.py (original) +++ pypy/dist/pypy/annotation/test/test_annrpython.py Wed Dec 6 03:13:50 2006 @@ -2363,6 +2363,18 @@ assert not s.nonneg py.test.raises(Exception, a.build_types, fun, [int, int]) + def test_sig_simpler(self): + def fun(x, y): + return x+y + s_nonneg = annmodel.SomeInteger(nonneg=True) + fun._annenforceargs_ = (int, s_nonneg) + + a = self.RPythonAnnotator() + s = a.build_types(fun, [s_nonneg, s_nonneg]) + assert isinstance(s, annmodel.SomeInteger) + assert not s.nonneg + py.test.raises(Exception, a.build_types, fun, [int, int]) + def test_sig_lambda(self): def fun(x, y): return y From pedronis at codespeak.net Wed Dec 6 03:30:19 2006 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Wed, 6 Dec 2006 03:30:19 +0100 (CET) Subject: [pypy-svn] r35362 - in pypy/branch/jit-real-world/pypy: annotation annotation/test rlib rpython rpython/test Message-ID: <20061206023019.DCB3E10082@code0.codespeak.net> Author: pedronis Date: Wed Dec 6 03:29:18 2006 New Revision: 35362 Modified: pypy/branch/jit-real-world/pypy/annotation/annrpython.py pypy/branch/jit-real-world/pypy/annotation/binaryop.py pypy/branch/jit-real-world/pypy/annotation/description.py pypy/branch/jit-real-world/pypy/annotation/test/test_annrpython.py pypy/branch/jit-real-world/pypy/rlib/rarithmetic.py pypy/branch/jit-real-world/pypy/rlib/ros.py pypy/branch/jit-real-world/pypy/rpython/raddress.py pypy/branch/jit-real-world/pypy/rpython/robject.py pypy/branch/jit-real-world/pypy/rpython/rptr.py pypy/branch/jit-real-world/pypy/rpython/rtyper.py pypy/branch/jit-real-world/pypy/rpython/test/test_rpbc.py Log: svn merge -r 35338:35361 http://codespeak.net/svn/pypy/dist/pypy/annotation annotation svn merge -r 35338:35361 http://codespeak.net/svn/pypy/dist/pypy/rpython rpython U rpython/raddress.py svn merge -r 35338:35361 http://codespeak.net/svn/pypy/dist/pypy/rlib rlib Modified: pypy/branch/jit-real-world/pypy/annotation/annrpython.py ============================================================================== --- pypy/branch/jit-real-world/pypy/annotation/annrpython.py (original) +++ pypy/branch/jit-real-world/pypy/annotation/annrpython.py Wed Dec 6 03:29:18 2006 @@ -645,6 +645,7 @@ last_exc_value_vars = [] in_except_block = True + ignore_link = False cells = [] renaming = {} for a,v in zip(link.args,link.target.inputargs): @@ -662,6 +663,9 @@ if (link.exitcase, a) in knowntypedata: knownvarvalue = knowntypedata[(link.exitcase, a)] cell = pair(cell, knownvarvalue).improve() + # ignore links that try to pass impossible values + if cell == annmodel.s_ImpossibleValue: + ignore_link = True if hasattr(cell,'is_type_of'): renamed_is_type_of = [] @@ -691,12 +695,12 @@ cells.append(cell) + if ignore_link: + continue + if in_except_block: last_exception_object.is_type_of = last_exc_value_vars - if annmodel.s_ImpossibleValue in cells: - continue # ignore links that try to pass impossible values - self.links_followed[link] = True self.addpendingblock(graph, link.target, cells) Modified: pypy/branch/jit-real-world/pypy/annotation/binaryop.py ============================================================================== --- pypy/branch/jit-real-world/pypy/annotation/binaryop.py (original) +++ pypy/branch/jit-real-world/pypy/annotation/binaryop.py Wed Dec 6 03:29:18 2006 @@ -630,11 +630,23 @@ return SomeBuiltin(bltn1.analyser, s_self, methodname=bltn1.methodname) class __extend__(pairtype(SomePBC, SomePBC)): + def union((pbc1, pbc2)): d = pbc1.descriptions.copy() d.update(pbc2.descriptions) return SomePBC(d, can_be_None = pbc1.can_be_None or pbc2.can_be_None) + def is_((obj1, obj2)): + thistype = pairtype(SomePBC, SomePBC) + s = super(thistype, pair(obj1, obj2)).is_() + if not s.is_constant(): + for desc in obj1.descriptions: + if desc in obj2.descriptions: + break + else: + s.const = False # no common desc in the two sets + return s + class __extend__(pairtype(SomeImpossibleValue, SomeObject)): def union((imp1, obj2)): return obj2 Modified: pypy/branch/jit-real-world/pypy/annotation/description.py ============================================================================== --- pypy/branch/jit-real-world/pypy/annotation/description.py (original) +++ pypy/branch/jit-real-world/pypy/annotation/description.py Wed Dec 6 03:29:18 2006 @@ -254,6 +254,10 @@ self.specializer = policy.get_specializer(tag) enforceargs = getattr(self.pyobj, '_annenforceargs_', None) if enforceargs: + if not callable(enforceargs): + from pypy.annotation.policy import Sig + enforceargs = Sig(*enforceargs) + self.pyobj._annenforceargs_ = enforceargs enforceargs(self, inputcells) # can modify inputcells in-place return self.specializer(self, inputcells) Modified: pypy/branch/jit-real-world/pypy/annotation/test/test_annrpython.py ============================================================================== --- pypy/branch/jit-real-world/pypy/annotation/test/test_annrpython.py (original) +++ pypy/branch/jit-real-world/pypy/annotation/test/test_annrpython.py Wed Dec 6 03:29:18 2006 @@ -2363,6 +2363,18 @@ assert not s.nonneg py.test.raises(Exception, a.build_types, fun, [int, int]) + def test_sig_simpler(self): + def fun(x, y): + return x+y + s_nonneg = annmodel.SomeInteger(nonneg=True) + fun._annenforceargs_ = (int, s_nonneg) + + a = self.RPythonAnnotator() + s = a.build_types(fun, [s_nonneg, s_nonneg]) + assert isinstance(s, annmodel.SomeInteger) + assert not s.nonneg + py.test.raises(Exception, a.build_types, fun, [int, int]) + def test_sig_lambda(self): def fun(x, y): return y Modified: pypy/branch/jit-real-world/pypy/rlib/rarithmetic.py ============================================================================== --- pypy/branch/jit-real-world/pypy/rlib/rarithmetic.py (original) +++ pypy/branch/jit-real-world/pypy/rlib/rarithmetic.py Wed Dec 6 03:29:18 2006 @@ -313,6 +313,7 @@ def specialize_call(self, hop): v_result, = hop.inputargs(hop.r_result.lowleveltype) + hop.exception_cannot_occur() return v_result return int_type Modified: pypy/branch/jit-real-world/pypy/rlib/ros.py ============================================================================== --- pypy/branch/jit-real-world/pypy/rlib/ros.py (original) +++ pypy/branch/jit-real-world/pypy/rlib/ros.py Wed Dec 6 03:29:18 2006 @@ -8,6 +8,7 @@ # we fake it with the real one name, value = name_eq_value.split('=', 1) os.putenv(name, value) +putenv._annenforceargs_ = (str,) _initial_items = os.environ.items() @@ -29,6 +30,7 @@ return value idx += 1 return None +getenv._annenforceargs_ = (str,) class DIR(object): @@ -49,3 +51,4 @@ def opendir(dirname): return DIR(dirname) +opendir._annenforceargs_ = (str,) Modified: pypy/branch/jit-real-world/pypy/rpython/raddress.py ============================================================================== --- pypy/branch/jit-real-world/pypy/rpython/raddress.py (original) +++ pypy/branch/jit-real-world/pypy/rpython/raddress.py Wed Dec 6 03:29:18 2006 @@ -7,6 +7,7 @@ from pypy.rpython.rmodel import Repr, IntegerRepr from pypy.rpython.rptr import PtrRepr from pypy.rpython.lltypesystem import lltype +from pypy.rlib.rarithmetic import r_uint class __extend__(annmodel.SomeAddress): def rtyper_makerepr(self, rtyper): @@ -36,6 +37,11 @@ assert not isinstance(value, _address) return value + def ll_str(self, a): + from pypy.rpython.lltypesystem.rstr import ll_str + id = cast_adr_to_int(a) + return ll_str.ll_int2hex(r_uint(id), True) + def rtype_getattr(self, hop): v_access = hop.inputarg(address_repr, 0) return v_access Modified: pypy/branch/jit-real-world/pypy/rpython/robject.py ============================================================================== --- pypy/branch/jit-real-world/pypy/rpython/robject.py (original) +++ pypy/branch/jit-real-world/pypy/rpython/robject.py Wed Dec 6 03:29:18 2006 @@ -9,19 +9,25 @@ class __extend__(annmodel.SomeObject): def rtyper_makerepr(self, rtyper): - if self.knowntype is type: + kind = getkind(self) + if kind == "type": return rclass.get_type_repr(rtyper) - elif self.is_constant(): + elif kind == "const": return constpyobj_repr else: return pyobj_repr def rtyper_makekey(self): - if self.is_constant(): - return self.__class__, "const" - if self.knowntype is type: - return self.__class__, "type" - else: - return self.__class__, "pyobj" + return self.__class__, getkind(self) + +def getkind(s_obj): + if s_obj.is_constant(): + if getattr(s_obj.const, '__module__', None) == '__builtin__': + return "const" + if s_obj.knowntype is type: + return "type" + if s_obj.is_constant(): + return "const" + return "pyobj" class PyObjRepr(Repr): Modified: pypy/branch/jit-real-world/pypy/rpython/rptr.py ============================================================================== --- pypy/branch/jit-real-world/pypy/rpython/rptr.py (original) +++ pypy/branch/jit-real-world/pypy/rpython/rptr.py Wed Dec 6 03:29:18 2006 @@ -27,7 +27,7 @@ self.lowleveltype = ptrtype def ll_str(self, p): - from pypy.rpython.lltypesystem.rstr import LLHelpers, ll_str + from pypy.rpython.lltypesystem.rstr import ll_str id = lltype.cast_ptr_to_int(p) return ll_str.ll_int2hex(r_uint(id), True) Modified: pypy/branch/jit-real-world/pypy/rpython/rtyper.py ============================================================================== --- pypy/branch/jit-real-world/pypy/rpython/rtyper.py (original) +++ pypy/branch/jit-real-world/pypy/rpython/rtyper.py Wed Dec 6 03:29:18 2006 @@ -244,12 +244,8 @@ bc += 1 continue block, position = err.where - func = self.annotator.annotated.get(block, None) - if func: - func = "(%s:%s)" %(func.__module__ or '?', func.__name__) - else: - func = "(?:?)" - errmsg = ("TyperError-%d: %s" % (c, func) + + graph = self.annotator.annotated.get(block, None) + errmsg = ("TyperError-%d: %s\n" % (c, graph) + str(err) + "\n") if to_log: Modified: pypy/branch/jit-real-world/pypy/rpython/test/test_rpbc.py ============================================================================== --- pypy/branch/jit-real-world/pypy/rpython/test/test_rpbc.py (original) +++ pypy/branch/jit-real-world/pypy/rpython/test/test_rpbc.py Wed Dec 6 03:29:18 2006 @@ -1477,6 +1477,20 @@ res = self.interpret(f, [5]) assert res == 123 + def test_is_among_functions(self): + def g1(): pass + def g2(): pass + def g3(): pass + def f(n): + if n > 5: + g = g2 + else: + g = g1 + g() + g3() + return g is g3 + res = self.interpret(f, [2]) + assert res == False # We don't care about the following test_hlinvoke tests working on # ootype. Maybe later. This kind of thing is only used in rdict From arigo at codespeak.net Wed Dec 6 03:31:07 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 6 Dec 2006 03:31:07 +0100 (CET) Subject: [pypy-svn] r35363 - pypy/branch/jit-real-world/pypy/module/pypyjit Message-ID: <20061206023107.5BA6810087@code0.codespeak.net> Author: arigo Date: Wed Dec 6 03:30:41 2006 New Revision: 35363 Modified: pypy/branch/jit-real-world/pypy/module/pypyjit/interp_jit.py Log: Re-oups oups oups! The portal is always the dispatch_jit... of course. Modified: pypy/branch/jit-real-world/pypy/module/pypyjit/interp_jit.py ============================================================================== --- pypy/branch/jit-real-world/pypy/module/pypyjit/interp_jit.py (original) +++ pypy/branch/jit-real-world/pypy/module/pypyjit/interp_jit.py Wed Dec 6 03:30:41 2006 @@ -50,8 +50,6 @@ else: return super_dispatch(self, co_code, next_instr, ec) - return PyFrame.dispatch_jit - def setup2(): # TEMPORARY: only patches dispatch_bytecode. PyFrame.dispatch_jit = func_with_new_name( @@ -66,9 +64,9 @@ else: return super_dispatch_bytecode(self, co_code, next_instr, ec) - return PyFrame.dispatch_bytecode +setup2() -PORTAL = setup2() +PORTAL = PyFrame.dispatch_jit # ____________________________________________________________ # From pedronis at codespeak.net Wed Dec 6 03:37:31 2006 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Wed, 6 Dec 2006 03:37:31 +0100 (CET) Subject: [pypy-svn] r35364 - in pypy/branch/jit-real-world/pypy/translator: . tool Message-ID: <20061206023731.12DF91006F@code0.codespeak.net> Author: pedronis Date: Wed Dec 6 03:36:56 2006 New Revision: 35364 Modified: pypy/branch/jit-real-world/pypy/translator/interactive.py pypy/branch/jit-real-world/pypy/translator/tool/graphpage.py Log: svn merge -r 35338:35361 http://codespeak.net/svn/pypy/dist/pypy/translator/interactive.py translator/interactive.py svn merge -r 35338:35361 http://codespeak.net/svn/pypy/dist/pypy/translator/tool/graphpage.py translator/tool/graphpage.py Modified: pypy/branch/jit-real-world/pypy/translator/interactive.py ============================================================================== --- pypy/branch/jit-real-world/pypy/translator/interactive.py (original) +++ pypy/branch/jit-real-world/pypy/translator/interactive.py Wed Dec 6 03:36:56 2006 @@ -19,9 +19,6 @@ self.entry_point = entry_point self.context = TranslationContext(config=self.config) - # for t.view() to work just after construction - graph = self.context.buildflowgraph(entry_point) - self.context._prebuilt_graphs[entry_point] = graph # hook into driver events driver_own_event = self.driver._event @@ -32,6 +29,9 @@ self.driver_setup = False self.update_options(argtypes, kwds) + # for t.view() to work just after construction + graph = self.context.buildflowgraph(entry_point) + self.context._prebuilt_graphs[entry_point] = graph def view(self): self.context.view() Modified: pypy/branch/jit-real-world/pypy/translator/tool/graphpage.py ============================================================================== --- pypy/branch/jit-real-world/pypy/translator/tool/graphpage.py (original) +++ pypy/branch/jit-real-world/pypy/translator/tool/graphpage.py Wed Dec 6 03:36:56 2006 @@ -375,7 +375,10 @@ that means just including direct callers and callees""" def graph_name(self, centers): - return 'LCG_%s' % nameof(centers[0]) + if centers: + return 'LCG_%s' % nameof(centers[0]) + else: + return 'EMPTY' def do_compute(self, dotgen, centers): centers = dict.fromkeys(centers) From cfbolz at codespeak.net Wed Dec 6 09:09:28 2006 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Wed, 6 Dec 2006 09:09:28 +0100 (CET) Subject: [pypy-svn] r35365 - pypy/dist/pypy/rpython/memory/gctransform/test Message-ID: <20061206080928.E517D10075@code0.codespeak.net> Author: cfbolz Date: Wed Dec 6 09:09:23 2006 New Revision: 35365 Modified: pypy/dist/pypy/rpython/memory/gctransform/test/test_framework.py Log: sorry for the trial-and-error check in yesterday :-(. fix the first of a row of tests that failed due to my refactoring. Modified: pypy/dist/pypy/rpython/memory/gctransform/test/test_framework.py ============================================================================== --- pypy/dist/pypy/rpython/memory/gctransform/test/test_framework.py (original) +++ pypy/dist/pypy/rpython/memory/gctransform/test/test_framework.py Wed Dec 6 09:09:23 2006 @@ -26,7 +26,8 @@ from pypy.annotation.listdef import s_list_of_strings t = rtype(entrypoint, [s_list_of_strings]) - cbuild = CStandaloneBuilder(t, entrypoint, gcpolicy=FrameworkGcPolicy2) + cbuild = CStandaloneBuilder(t, entrypoint, t.config, + gcpolicy=FrameworkGcPolicy2) db = cbuild.generate_graphs_for_llinterp() entrypointptr = cbuild.getentrypointptr() entrygraph = entrypointptr._obj.graph From cfbolz at codespeak.net Wed Dec 6 09:10:39 2006 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Wed, 6 Dec 2006 09:10:39 +0100 (CET) Subject: [pypy-svn] r35366 - pypy/dist/pypy/translator/test Message-ID: <20061206081039.5B16610079@code0.codespeak.net> Author: cfbolz Date: Wed Dec 6 09:10:37 2006 New Revision: 35366 Modified: pypy/dist/pypy/translator/test/test_extension.py Log: next one Modified: pypy/dist/pypy/translator/test/test_extension.py ============================================================================== --- pypy/dist/pypy/translator/test/test_extension.py (original) +++ pypy/dist/pypy/translator/test/test_extension.py Wed Dec 6 09:10:37 2006 @@ -33,7 +33,7 @@ if use_boehm: gcpolicy = gc.BoehmGcPolicy - cbuilder = CExtModuleBuilder(t, func, gcpolicy=gcpolicy) + cbuilder = CExtModuleBuilder(t, func, t.config, gcpolicy=gcpolicy) cbuilder.generate_source() cbuilder.compile() From cfbolz at codespeak.net Wed Dec 6 10:52:53 2006 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Wed, 6 Dec 2006 10:52:53 +0100 (CET) Subject: [pypy-svn] r35368 - pypy/dist/pypy/translator/c/test Message-ID: <20061206095253.E225710075@code0.codespeak.net> Author: cfbolz Date: Wed Dec 6 10:52:51 2006 New Revision: 35368 Modified: pypy/dist/pypy/translator/c/test/test_boehm.py pypy/dist/pypy/translator/c/test/test_genc.py pypy/dist/pypy/translator/c/test/test_standalone.py Log: fix two more issues with the config changes. Modified: pypy/dist/pypy/translator/c/test/test_boehm.py ============================================================================== --- pypy/dist/pypy/translator/c/test/test_boehm.py (original) +++ pypy/dist/pypy/translator/c/test/test_boehm.py Wed Dec 6 10:52:51 2006 @@ -1,5 +1,6 @@ import py from pypy.translator.translator import TranslationContext +from pypy.rpython.lltypesystem.lltype import Void from pypy.translator.tool.cbuild import check_boehm_presence from pypy.translator.c.genc import CExtModuleBuilder from pypy import conftest @@ -176,6 +177,31 @@ res = fn() assert res == 10 + # this test shows if we have a problem with refcounting PyObject + def test_refcount_pyobj(self): + from pypy.rpython.lltypesystem.lloperation import llop + def prob_with_pyobj(b): + return 3, b + def collect(): + llop.gc__collect(Void) + f = self.getcompiled(prob_with_pyobj, [object]) + c = self.getcompiled(collect, []) + from sys import getrefcount as g + obj = None + before = g(obj) + f(obj) + f(obj) + f(obj) + f(obj) + f(obj) + c() + c() + c() + c() + c() + after = g(obj) + assert abs(before - after) < 5 + class TestUsingExactBoehm(TestUsingBoehm): gcpolicy = "exact_boehm" Modified: pypy/dist/pypy/translator/c/test/test_genc.py ============================================================================== --- pypy/dist/pypy/translator/c/test/test_genc.py (original) +++ pypy/dist/pypy/translator/c/test/test_genc.py Wed Dec 6 10:52:51 2006 @@ -285,43 +285,17 @@ f1 = compile(f, []) assert f1() == 1 -# this test shows if we have a problem with refcounting PyObject -if conftest.option.gcpolicy == 'boehm': - def test_refcount_pyobj(): - from pypy.rpython.lltypesystem.lloperation import llop - def prob_with_pyobj(b): - return 3, b - def collect(): - llop.gc__collect(Void) - f = compile(prob_with_pyobj, [object]) - c = compile(collect, []) - from sys import getrefcount as g - obj = None - before = g(obj) - f(obj) - f(obj) - f(obj) - f(obj) - f(obj) - c() - c() - c() - c() - c() - after = g(obj) - assert abs(before - after) < 5 -else: - def test_refcount_pyobj(): - def prob_with_pyobj(b): - return 3, b - - f = compile(prob_with_pyobj, [object]) - from sys import getrefcount as g - obj = None - before = g(obj) - f(obj) - after = g(obj) - assert before == after +def test_refcount_pyobj(): + def prob_with_pyobj(b): + return 3, b + + f = compile(prob_with_pyobj, [object]) + from sys import getrefcount as g + obj = None + before = g(obj) + f(obj) + after = g(obj) + assert before == after def test_refcount_pyobj_setfield(): import weakref, gc Modified: pypy/dist/pypy/translator/c/test/test_standalone.py ============================================================================== --- pypy/dist/pypy/translator/c/test/test_standalone.py (original) +++ pypy/dist/pypy/translator/c/test/test_standalone.py Wed Dec 6 10:52:51 2006 @@ -20,7 +20,7 @@ t.buildannotator().build_types(entry_point, [s_list_of_strings]) t.buildrtyper().specialize() - cbuilder = CStandaloneBuilder(t, entry_point) + cbuilder = CStandaloneBuilder(t, entry_point, t.config) cbuilder.generate_source() cbuilder.compile() data = cbuilder.cmdexec('hi there') @@ -40,7 +40,7 @@ t.buildannotator().build_types(entry_point, [s_list_of_strings]) t.buildrtyper().specialize() - cbuilder = CStandaloneBuilder(t, entry_point) + cbuilder = CStandaloneBuilder(t, entry_point, t.config) cbuilder.generate_source() cbuilder.compile() data = cbuilder.cmdexec('hi there') From ericvrp at codespeak.net Wed Dec 6 11:58:11 2006 From: ericvrp at codespeak.net (ericvrp at codespeak.net) Date: Wed, 6 Dec 2006 11:58:11 +0100 (CET) Subject: [pypy-svn] r35369 - in pypy/dist/pypy/jit/codegen/llvm: . test Message-ID: <20061206105811.7638210075@code0.codespeak.net> Author: ericvrp Date: Wed Dec 6 11:58:08 2006 New Revision: 35369 Modified: pypy/dist/pypy/jit/codegen/llvm/llvmjit.py pypy/dist/pypy/jit/codegen/llvm/rgenop.py pypy/dist/pypy/jit/codegen/llvm/test/test_llvmjit.py pypy/dist/pypy/jit/codegen/llvm/test/test_rgenop.py Log: Another passing llvmjit rgenop test + quite a few opcodes implemented. Modified: pypy/dist/pypy/jit/codegen/llvm/llvmjit.py ============================================================================== --- pypy/dist/pypy/jit/codegen/llvm/llvmjit.py (original) +++ pypy/dist/pypy/jit/codegen/llvm/llvmjit.py Wed Dec 6 11:58:08 2006 @@ -67,9 +67,13 @@ getNamedGlobal.argtypes = [c_char_p] getPointerToFunction = llvmjit.getPointerToFunction -getPointerToFunction.restype = c_void_p +getPointerToFunction.restype = c_void_p getPointerToFunction.argtypes = [c_void_p] +getPointerToFunctionAsInt = llvmjit.getPointerToFunction +getPointerToFunctionAsInt.restype = c_int +getPointerToFunctionAsInt.argtypes = [c_void_p] + freeMachineCodeForFunction = llvmjit.freeMachineCodeForFunction freeMachineCodeForFunction.restype = c_int freeMachineCodeForFunction.argtypes = [c_void_p] Modified: pypy/dist/pypy/jit/codegen/llvm/rgenop.py ============================================================================== --- pypy/dist/pypy/jit/codegen/llvm/rgenop.py (original) +++ pypy/dist/pypy/jit/codegen/llvm/rgenop.py Wed Dec 6 11:58:08 2006 @@ -10,14 +10,14 @@ pass -n_vars = 0 +n_vars = [0] class Var(GenVar): def __init__(self): global n_vars - self.name = '%v' + str(n_vars) - n_vars += 1 + self.name = '%v' + str(n_vars[0]) + n_vars[0] += 1 def operand(self): return 'int ' + self.name @@ -165,8 +165,14 @@ class Builder(object): #changed baseclass from (GenBuilder) for better error messages + _genop2_generics = { + 'int_add' : 'add' , 'int_sub' : 'sub' , 'int_mul' : 'mul' , 'int_floordiv' : 'div' , + 'int_mod' : 'rem' , 'int_and' : 'and' , 'int_or' : 'or' , 'int_xor' : 'xor' , + 'int_lt' : 'setlt', 'int_le' : 'setle', 'int_eq' : 'seteq', 'int_ne' : 'setne', + 'int_gt' : 'setgt', 'int_ge' : 'setge' + } + def __init__(self, rgenop): - log('Builder.__init__') self.rgenop = rgenop self.asm = [] #list of llvm assembly source code lines @@ -180,45 +186,45 @@ log(asm_string) llvmjit.parse(asm_string) function = llvmjit.getNamedFunction(self.rgenop.name) - entrypoint = llvmjit.getPointerToFunction(function) + entrypoint = llvmjit.getPointerToFunctionAsInt(function) #how to cast a ctypes ptr to int? self.rgenop.gv_entrypoint.value = entrypoint - #print self.rgenop.name, 'entrypoint', entrypoint - #print self.rgenop.gv_entrypoint, self.rgenop.gv_entrypoint.value def _write_prologue(self, sigtoken): - log('Builder._write_prologue') numargs = sigtoken # for now inputargs_gv = [Var() for i in range(numargs)] self.asm.append('int %%%s(%s){' % ( self.rgenop.name, ','.join([v.operand() for v in inputargs_gv]))) return inputargs_gv - def _close(self): - log('Builder._close') - #self.mc.done() - #self.rgenop.close_mc(self.mc) - #self.mc = None - @specialize.arg(1) def genop1(self, opname, gv_arg): - log('Builder.genop1') + #log('Builder.genop1') genmethod = getattr(self, 'op_' + opname) return genmethod(gv_arg) @specialize.arg(1) def genop2(self, opname, gv_arg1, gv_arg2): - log('Builder.genop2') - genmethod = getattr(self, 'op_' + opname) - return genmethod(gv_arg1, gv_arg2) + #log('Builder.genop2') + if opname in self._genop2_generics: + return self._rgenop2_generic(self._genop2_generics[opname], gv_arg1, gv_arg2) + else: + genmethod = getattr(self, 'op_' + opname) + return genmethod(gv_arg1, gv_arg2) - def op_int_add(self, gv_x, gv_y): - log('Builder.op_int_add') + def _rgenop2_generic(self, llvm_opcode, gv_arg1, gv_arg2): + log('Builder._rgenop2_generic: ' + llvm_opcode) gv_result = Var() - self.asm.append(" %s=add %s,%s" % (gv_result.name, gv_x.operand(), gv_y.operand2())) + self.asm.append(" %s=%s %s,%s" % ( + gv_result.name, llvm_opcode, gv_arg1.operand(), gv_arg2.operand2())) return gv_result - #self.mc.MOV(eax, gv_x.operand(self)) - #self.mc.ADD(eax, gv_y.operand(self)) - #return self.returnvar(eax) + + #def op_int_neg(self, gv_x): + #def op_int_abs(self, gv_x): + #def op_int_invert(self, gv_x): + #def op_int_lshift(self, gv_x, gv_y): + #def op_int_rshift(self, gv_x, gv_y): + #def op_bool_not(self, gv_x): + #def op_cast_bool_to_int(self, gv_x): def enter_next_block(self, kinds, args_gv): log('Builder.enter_next_block TODO') @@ -243,19 +249,19 @@ #self.mc.MOV(eax, gv_returnvar.operand(self)) #self.mc.ADD(esp, imm(WORD * (self.stackdepth - initialstackdepth))) #self.mc.RET() - self._close() + #self._close() def finish_and_goto(self, outputargs_gv, target): log('Builder.finish_and_goto TODO') #remap_stack_layout(self, outputargs_gv, target) #self.mc.JMP(rel32(target.startaddr)) - self._close() + #self._close() def flexswitch(self, gv_exitswitch): log('Builder.flexswitch TODO') result = FlexSwitch(self.rgenop) result.initialize(self, gv_exitswitch) - self._close() + #self._close() return result def show_incremental_progress(self): @@ -274,7 +280,7 @@ # the public RGenOp interface def openbuilder(self): - log('RLLVMGenOp.openbuilder') + #log('RLLVMGenOp.openbuilder') return Builder(self) def newgraph(self, sigtoken, name): @@ -282,9 +288,8 @@ numargs = sigtoken # for now self.name = name builder = self.openbuilder() - #entrypoint = builder.asm.mc.tell() - self.gv_entrypoint = IntConst(0) inputargs_gv = builder._write_prologue(sigtoken) + self.gv_entrypoint = IntConst(0) #note: updated by Builder.end() (i.e after compilation) return builder, self.gv_entrypoint, inputargs_gv @specialize.genconst(1) Modified: pypy/dist/pypy/jit/codegen/llvm/test/test_llvmjit.py ============================================================================== --- pypy/dist/pypy/jit/codegen/llvm/test/test_llvmjit.py (original) +++ pypy/dist/pypy/jit/codegen/llvm/test/test_llvmjit.py Wed Dec 6 11:58:08 2006 @@ -1,7 +1,12 @@ import py from sys import platform from os.path import dirname, join -from pypy.translator.c.test.test_genc import compile + +try: + from pypy.translator.c.test.test_genc import compile + import_error = False #XXX temporary HACK until problem solves itself. +except AttributeError: #AttributeError: Values instance has no attribute 'gcpolicy' + import_error = True #pypy/translator/c/test/test_genc.py:289 from pypy.jit.codegen.llvm import llvmjit @@ -243,8 +248,10 @@ pass def test_execute_translation(): #put this one last because it takes the most time + if import_error: + py.test.skip("import error") if platform == 'darwin': - py.test.skip('dynamic vs. static library issue. see: http://www.cocoadev.com/index.pl?ApplicationLinkingIssues for more information (needs to be fixed)') + py.test.skip('dynamic vs. static library issue on Darwin. see: http://www.cocoadev.com/index.pl?ApplicationLinkingIssues for more information (FIXME)') llvmjit.restart() def f(x): Modified: pypy/dist/pypy/jit/codegen/llvm/test/test_rgenop.py ============================================================================== --- pypy/dist/pypy/jit/codegen/llvm/test/test_rgenop.py (original) +++ pypy/dist/pypy/jit/codegen/llvm/test/test_rgenop.py Wed Dec 6 11:58:08 2006 @@ -1,31 +1,23 @@ import py from pypy.jit.codegen.llvm.rgenop import RLLVMGenOp from pypy.jit.codegen.test.rgenop_tests import AbstractRGenOpTests -from pypy.rpython.lltypesystem import lltype -from ctypes import c_void_p, cast, CFUNCTYPE, c_int +from sys import platform -FUNC = lltype.FuncType([lltype.Signed], lltype.Signed) +class TestRLLVMGenop(AbstractRGenOpTests): + RGenOp = RLLVMGenOp -def make_adder(rgenop, n): - # 'return x+n' - sigtoken = rgenop.sigToken(FUNC) - builder, gv_add_one, [gv_x] = rgenop.newgraph(sigtoken, "adder") - #note: entrypoint (gv_add_one.value) gets updated by builder.end() (don't use before that!) - gv_result = builder.genop2("int_add", gv_x, rgenop.genconst(n)) - builder.finish_and_return(sigtoken, gv_result) - builder.end() - return gv_add_one - -def test_adder_direct(): - rgenop = RLLVMGenOp() - gv_add_5 = make_adder(rgenop, 5) - fnptr = cast(c_void_p(gv_add_5.value), CFUNCTYPE(c_int, c_int)) - #fnptr = gv_add_5.revealconst(lltype.Ptr(FUNC)) - res = fnptr(37) - assert res == 42 + def compile(self, runner, argtypes): + if platform == 'darwin': + py.test.skip('Compilation for Darwin not fully support yet (static/dyn lib issue') + super(TestRLLVMGenop, self).compile(runner.argtypes) -#class TestRLLVMGenop(AbstractRGenOpTests): -# RGenOp = RLLVMGenOp + def test_branching_direct(self): + py.test.skip('WIP') + test_goto_direct = test_branching_direct + test_if_direct = test_branching_direct + test_switch_direct = test_branching_direct + test_large_switch_direct = test_branching_direct + test_fact_direct = test_branching_direct From guido at codespeak.net Wed Dec 6 12:12:54 2006 From: guido at codespeak.net (guido at codespeak.net) Date: Wed, 6 Dec 2006 12:12:54 +0100 (CET) Subject: [pypy-svn] r35371 - pypy/dist/pypy/translator/js/modules Message-ID: <20061206111254.3139B10079@code0.codespeak.net> Author: guido Date: Wed Dec 6 12:12:53 2006 New Revision: 35371 Modified: pypy/dist/pypy/translator/js/modules/dom.py Log: Oops, debug print. Modified: pypy/dist/pypy/translator/js/modules/dom.py ============================================================================== --- pypy/dist/pypy/translator/js/modules/dom.py (original) +++ pypy/dist/pypy/translator/js/modules/dom.py Wed Dec 6 12:12:53 2006 @@ -87,7 +87,6 @@ def __setattr__(self, name, value): """set an attribute on the wrapped node""" - print dir(self) if name in dir(self): return super(Node, self).__setattr__(name, value) if name not in self._fields: @@ -435,7 +434,7 @@ 'blur' : MethodDesc([]), 'click' : MethodDesc([]), 'focus' : MethodDesc([]), - 'scrollIntoView' : MethodDesc([12]), + 'scrollIntoView' : MethodDesc([]), 'supports' : MethodDesc(["aa", 1.0]), }) From pedronis at codespeak.net Wed Dec 6 12:26:45 2006 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Wed, 6 Dec 2006 12:26:45 +0100 (CET) Subject: [pypy-svn] r35373 - pypy/dist/pypy/annotation Message-ID: <20061206112645.372411006F@code0.codespeak.net> Author: pedronis Date: Wed Dec 6 12:26:43 2006 New Revision: 35373 Modified: pypy/dist/pypy/annotation/binaryop.py Log: oops, pbc disjointness should consider can_be_None Modified: pypy/dist/pypy/annotation/binaryop.py ============================================================================== --- pypy/dist/pypy/annotation/binaryop.py (original) +++ pypy/dist/pypy/annotation/binaryop.py Wed Dec 6 12:26:43 2006 @@ -636,15 +636,16 @@ d.update(pbc2.descriptions) return SomePBC(d, can_be_None = pbc1.can_be_None or pbc2.can_be_None) - def is_((obj1, obj2)): + def is_((pbc1, pbc2)): thistype = pairtype(SomePBC, SomePBC) - s = super(thistype, pair(obj1, obj2)).is_() + s = super(thistype, pair(pbc1, pbc2)).is_() if not s.is_constant(): - for desc in obj1.descriptions: - if desc in obj2.descriptions: - break - else: - s.const = False # no common desc in the two sets + if not pbc1.can_be_None or not pbc2.can_be_None: + for desc in pbc1.descriptions: + if desc in pbc2.descriptions: + break + else: + s.const = False # no common desc in the two sets return s class __extend__(pairtype(SomeImpossibleValue, SomeObject)): From pedronis at codespeak.net Wed Dec 6 12:49:50 2006 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Wed, 6 Dec 2006 12:49:50 +0100 (CET) Subject: [pypy-svn] r35381 - pypy/branch/jit-real-world/pypy/annotation Message-ID: <20061206114950.7B7D41007B@code0.codespeak.net> Author: pedronis Date: Wed Dec 6 12:49:48 2006 New Revision: 35381 Modified: pypy/branch/jit-real-world/pypy/annotation/binaryop.py Log: svn merge -r35361:HEAD http://codespeak.net/svn/pypy/dist/pypy/annotation annotation Modified: pypy/branch/jit-real-world/pypy/annotation/binaryop.py ============================================================================== --- pypy/branch/jit-real-world/pypy/annotation/binaryop.py (original) +++ pypy/branch/jit-real-world/pypy/annotation/binaryop.py Wed Dec 6 12:49:48 2006 @@ -636,15 +636,16 @@ d.update(pbc2.descriptions) return SomePBC(d, can_be_None = pbc1.can_be_None or pbc2.can_be_None) - def is_((obj1, obj2)): + def is_((pbc1, pbc2)): thistype = pairtype(SomePBC, SomePBC) - s = super(thistype, pair(obj1, obj2)).is_() + s = super(thistype, pair(pbc1, pbc2)).is_() if not s.is_constant(): - for desc in obj1.descriptions: - if desc in obj2.descriptions: - break - else: - s.const = False # no common desc in the two sets + if not pbc1.can_be_None or not pbc2.can_be_None: + for desc in pbc1.descriptions: + if desc in pbc2.descriptions: + break + else: + s.const = False # no common desc in the two sets return s class __extend__(pairtype(SomeImpossibleValue, SomeObject)): From ac at codespeak.net Wed Dec 6 13:14:18 2006 From: ac at codespeak.net (ac at codespeak.net) Date: Wed, 6 Dec 2006 13:14:18 +0100 (CET) Subject: [pypy-svn] r35382 - in pypy/branch/jit-real-world/pypy/rpython: . ootypesystem Message-ID: <20061206121418.908451006F@code0.codespeak.net> Author: ac Date: Wed Dec 6 13:14:16 2006 New Revision: 35382 Modified: pypy/branch/jit-real-world/pypy/rpython/ootypesystem/ooregistry.py pypy/branch/jit-real-world/pypy/rpython/ootypesystem/rbuiltin.py pypy/branch/jit-real-world/pypy/rpython/ootypesystem/rclass.py pypy/branch/jit-real-world/pypy/rpython/ootypesystem/rstr.py pypy/branch/jit-real-world/pypy/rpython/rtyper.py Log: Oops, we forgot this. svn merge -r 35308:35309 http://codespeak.net/svn/pypy/dist/pypy/rpython Modified: pypy/branch/jit-real-world/pypy/rpython/ootypesystem/ooregistry.py ============================================================================== --- pypy/branch/jit-real-world/pypy/rpython/ootypesystem/ooregistry.py (original) +++ pypy/branch/jit-real-world/pypy/rpython/ootypesystem/ooregistry.py Wed Dec 6 13:14:16 2006 @@ -21,8 +21,8 @@ annmodel.SomeFloat, annmodel.SomeOOInstance, annmodel.SomeString)) - assert isinstance(hop.args_s[1], annmodel.SomeInteger) - return hop.genop('oostring', hop.args_v, resulttype = ootype.String) + vlist = hop.inputargs(hop.args_r[0], ootype.Signed) + return hop.genop('oostring', vlist, resulttype = ootype.String) class Entry_ootype_string(ExtRegistryEntry): @@ -44,10 +44,10 @@ def specialize_call(self, hop): assert isinstance(hop.args_s[0], annmodel.SomeOOInstance)\ and hop.args_s[0].ootype is ootype.String - assert isinstance(hop.args_s[1], annmodel.SomeInteger) + vlist = hop.inputargs(hop.args_r[0], ootype.Signed) hop.has_implicit_exception(ValueError) hop.exception_is_here() - return hop.genop('ooparse_int', hop.args_v, resulttype = ootype.Signed) + return hop.genop('ooparse_int', vlist, resulttype = ootype.Signed) class Entry_oohash(ExtRegistryEntry): _about_ = ootype.oohash @@ -60,4 +60,5 @@ def specialize_call(self, hop): assert isinstance(hop.args_s[0], annmodel.SomeOOInstance)\ and hop.args_s[0].ootype is ootype.String - return hop.genop('oohash', hop.args_v, resulttype=ootype.Signed) + vlist = hop.inputargs(hop.args_r[0]) + return hop.genop('oohash', vlist, resulttype=ootype.Signed) Modified: pypy/branch/jit-real-world/pypy/rpython/ootypesystem/rbuiltin.py ============================================================================== --- pypy/branch/jit-real-world/pypy/rpython/ootypesystem/rbuiltin.py (original) +++ pypy/branch/jit-real-world/pypy/rpython/ootypesystem/rbuiltin.py Wed Dec 6 13:14:16 2006 @@ -1,5 +1,5 @@ from pypy.annotation import model as annmodel -from pypy.rpython.ootypesystem import ootype +from pypy.rpython.ootypesystem import ootype, rootype from pypy.rpython.ootypesystem import rclass from pypy.rpython.ootypesystem.rdict import rtype_r_dict from pypy.objspace.flow.model import Constant @@ -20,23 +20,24 @@ def rtype_classof(hop): assert isinstance(hop.args_s[0], annmodel.SomeOOInstance) - return hop.genop('classof', hop.args_v, + vlist = hop.inputargs(hop.args_r[0]) + return hop.genop('classof', vlist, resulttype = ootype.Class) def rtype_subclassof(hop): - assert isinstance(hop.args_s[0], annmodel.SomeOOClass) - assert isinstance(hop.args_s[1], annmodel.SomeOOClass) - return hop.genop('subclassof', hop.args_v, + vlist = hop.inputargs(rootype.ooclass_repr, rootype.ooclass_repr) + return hop.genop('subclassof', vlist, resulttype = ootype.Bool) def rtype_runtimenew(hop): - assert isinstance(hop.args_s[0], annmodel.SomeOOClass) - return hop.genop('runtimenew', hop.args_v, + vlist = hop.inputargs(rootype.ooclass_repr) + return hop.genop('runtimenew', vlist, resulttype = hop.r_result.lowleveltype) def rtype_ooidentityhash(hop): assert isinstance(hop.args_s[0], annmodel.SomeOOInstance) - return hop.genop('ooidentityhash', hop.args_v, + vlist = hop.inputargs(hop.args_r[0]) + return hop.genop('ooidentityhash', vlist, resulttype = ootype.Signed) def rtype_builtin_isinstance(hop): Modified: pypy/branch/jit-real-world/pypy/rpython/ootypesystem/rclass.py ============================================================================== --- pypy/branch/jit-real-world/pypy/rpython/ootypesystem/rclass.py (original) +++ pypy/branch/jit-real-world/pypy/rpython/ootypesystem/rclass.py Wed Dec 6 13:14:16 2006 @@ -399,12 +399,8 @@ vinst, = hop.inputargs(self) return hop.genop('oononnull', [vinst], resulttype=ootype.Bool) - def ll_const(c): - return c - ll_const = staticmethod(ll_const) - def ll_str(self, instance): - return ootype.oostring(instance, self.ll_const(-1)) + return ootype.oostring(instance, -1) def rtype_type(self, hop): if hop.s_result.is_constant(): Modified: pypy/branch/jit-real-world/pypy/rpython/ootypesystem/rstr.py ============================================================================== --- pypy/branch/jit-real-world/pypy/rpython/ootypesystem/rstr.py (original) +++ pypy/branch/jit-real-world/pypy/rpython/ootypesystem/rstr.py Wed Dec 6 13:14:16 2006 @@ -61,11 +61,8 @@ class LLHelpers(AbstractLLHelpers): - def ll_const(c): - return c - def ll_chr2str(ch): - return ootype.oostring(ch, LLHelpers.ll_const(-1)) + return ootype.oostring(ch, -1) def ll_strhash(s): return ootype.oohash(s) Modified: pypy/branch/jit-real-world/pypy/rpython/rtyper.py ============================================================================== --- pypy/branch/jit-real-world/pypy/rpython/rtyper.py (original) +++ pypy/branch/jit-real-world/pypy/rpython/rtyper.py Wed Dec 6 13:14:16 2006 @@ -717,6 +717,8 @@ return vars def genop(self, opname, args_v, resulttype=None): + assert args_v is not self.args_v, ("Wrong level! " + "You need to pass the result of hop.inputargs() to genop().") return self.llops.genop(opname, args_v, resulttype) def gendirectcall(self, ll_function, *args_v): From mwh at codespeak.net Wed Dec 6 13:25:58 2006 From: mwh at codespeak.net (mwh at codespeak.net) Date: Wed, 6 Dec 2006 13:25:58 +0100 (CET) Subject: [pypy-svn] r35383 - pypy/extradoc/sprintinfo/leysin-winter-2007 Message-ID: <20061206122558.8458810070@code0.codespeak.net> Author: mwh Date: Wed Dec 6 13:25:56 2006 New Revision: 35383 Modified: pypy/extradoc/sprintinfo/leysin-winter-2007/people.txt Log: my dates Modified: pypy/extradoc/sprintinfo/leysin-winter-2007/people.txt ============================================================================== --- pypy/extradoc/sprintinfo/leysin-winter-2007/people.txt (original) +++ pypy/extradoc/sprintinfo/leysin-winter-2007/people.txt Wed Dec 6 13:25:56 2006 @@ -16,6 +16,7 @@ Armin Rigo -- private Anders Chrigstroem 6th-15th Ermina Samuele Pedroni 6th-15th Ermina +Michael Hudson 7th-15th Ermina ==================== ============== ===================== People on the following list were present at previous sprints: From ac at codespeak.net Wed Dec 6 13:30:05 2006 From: ac at codespeak.net (ac at codespeak.net) Date: Wed, 6 Dec 2006 13:30:05 +0100 (CET) Subject: [pypy-svn] r35384 - pypy/dist/pypy/translator/tool Message-ID: <20061206123005.4F72510070@code0.codespeak.net> Author: ac Date: Wed Dec 6 13:30:04 2006 New Revision: 35384 Modified: pypy/dist/pypy/translator/tool/make_dot.py Log: Pretty pretty colours. Modified: pypy/dist/pypy/translator/tool/make_dot.py ============================================================================== --- pypy/dist/pypy/translator/tool/make_dot.py (original) +++ pypy/dist/pypy/translator/tool/make_dot.py Wed Dec 6 13:30:04 2006 @@ -76,7 +76,8 @@ TAG_TO_COLORS = { "timeshifted": "#cfa5f0", - "portal_entry": "#f084c2" + "portal_entry": "#84abf0", + "portal_reentry": "#f084c2", } DEFAULT_TAG_COLOR = "#a5e6f0" RETURN_COLOR = "green" From ac at codespeak.net Wed Dec 6 13:32:01 2006 From: ac at codespeak.net (ac at codespeak.net) Date: Wed, 6 Dec 2006 13:32:01 +0100 (CET) Subject: [pypy-svn] r35385 - pypy/branch/jit-real-world/pypy/translator/tool Message-ID: <20061206123201.E10E210075@code0.codespeak.net> Author: ac Date: Wed Dec 6 13:32:01 2006 New Revision: 35385 Modified: pypy/branch/jit-real-world/pypy/translator/tool/make_dot.py Log: svn merge -r 35383:35384 svn+ssh://codespeak.net/svn/pypy/dist/pypy/translator/tool Modified: pypy/branch/jit-real-world/pypy/translator/tool/make_dot.py ============================================================================== --- pypy/branch/jit-real-world/pypy/translator/tool/make_dot.py (original) +++ pypy/branch/jit-real-world/pypy/translator/tool/make_dot.py Wed Dec 6 13:32:01 2006 @@ -77,7 +77,8 @@ TAG_TO_COLORS = { "timeshifted": "#cfa5f0", - "portal_entry": "#f084c2" + "portal_entry": "#84abf0", + "portal_reentry": "#f084c2", } DEFAULT_TAG_COLOR = "#a5e6f0" RETURN_COLOR = "green" From arigo at codespeak.net Wed Dec 6 13:36:26 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 6 Dec 2006 13:36:26 +0100 (CET) Subject: [pypy-svn] r35386 - pypy/dist/pypy/rpython/test Message-ID: <20061206123626.B56361007C@code0.codespeak.net> Author: arigo Date: Wed Dec 6 13:36:25 2006 New Revision: 35386 Modified: pypy/dist/pypy/rpython/test/test_exception.py Log: This test actually passes now. Modified: pypy/dist/pypy/rpython/test/test_exception.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_exception.py (original) +++ pypy/dist/pypy/rpython/test/test_exception.py Wed Dec 6 13:36:25 2006 @@ -69,7 +69,6 @@ assert res == 42 def test_catch_incompatible_class(self): - import py; py.test.skip("in-progress") class MyError(Exception): pass def h(x): From arigo at codespeak.net Wed Dec 6 13:36:58 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 6 Dec 2006 13:36:58 +0100 (CET) Subject: [pypy-svn] r35387 - pypy/dist/pypy/rpython Message-ID: <20061206123658.731EB10079@code0.codespeak.net> Author: arigo Date: Wed Dec 6 13:36:57 2006 New Revision: 35387 Modified: pypy/dist/pypy/rpython/rtyper.py Log: A more detailed sanity-checking logic. Avoids crashes in the jit, too. Modified: pypy/dist/pypy/rpython/rtyper.py ============================================================================== --- pypy/dist/pypy/rpython/rtyper.py (original) +++ pypy/dist/pypy/rpython/rtyper.py Wed Dec 6 13:36:57 2006 @@ -712,8 +712,6 @@ return vars def genop(self, opname, args_v, resulttype=None): - assert args_v is not self.args_v, ("Wrong level! " - "You need to pass the result of hop.inputargs() to genop().") return self.llops.genop(opname, args_v, resulttype) def gendirectcall(self, ll_function, *args_v): @@ -824,6 +822,13 @@ return v def genop(self, opname, args_v, resulttype=None): + try: + for v in args_v: + v.concretetype + except AttributeError: + raise AssertionError("wrong level! you must call hop.inputargs()" + " and pass its result to genop()," + " never hop.args_v directly.") vresult = Variable() self.append(SpaceOperation(opname, args_v, vresult)) if resulttype is None: From arigo at codespeak.net Wed Dec 6 13:40:50 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 6 Dec 2006 13:40:50 +0100 (CET) Subject: [pypy-svn] r35388 - pypy/branch/jit-real-world/pypy/rpython Message-ID: <20061206124050.0F29010070@code0.codespeak.net> Author: arigo Date: Wed Dec 6 13:40:49 2006 New Revision: 35388 Modified: pypy/branch/jit-real-world/pypy/rpython/rtyper.py Log: svn merge -r 35361:35387 http://codespeak.net/svn/pypy/dist/pypy/rpython/rtyper.py rpython/ Modified: pypy/branch/jit-real-world/pypy/rpython/rtyper.py ============================================================================== --- pypy/branch/jit-real-world/pypy/rpython/rtyper.py (original) +++ pypy/branch/jit-real-world/pypy/rpython/rtyper.py Wed Dec 6 13:40:49 2006 @@ -717,8 +717,6 @@ return vars def genop(self, opname, args_v, resulttype=None): - assert args_v is not self.args_v, ("Wrong level! " - "You need to pass the result of hop.inputargs() to genop().") return self.llops.genop(opname, args_v, resulttype) def gendirectcall(self, ll_function, *args_v): @@ -829,6 +827,13 @@ return v def genop(self, opname, args_v, resulttype=None): + try: + for v in args_v: + v.concretetype + except AttributeError: + raise AssertionError("wrong level! you must call hop.inputargs()" + " and pass its result to genop()," + " never hop.args_v directly.") vresult = Variable() self.append(SpaceOperation(opname, args_v, vresult)) if resulttype is None: From mwh at codespeak.net Wed Dec 6 14:02:35 2006 From: mwh at codespeak.net (mwh at codespeak.net) Date: Wed, 6 Dec 2006 14:02:35 +0100 (CET) Subject: [pypy-svn] r35389 - pypy/branch/builtin-call-speedup/pypy/interpreter Message-ID: <20061206130235.6C70010083@code0.codespeak.net> Author: mwh Date: Wed Dec 6 14:02:34 2006 New Revision: 35389 Modified: pypy/branch/builtin-call-speedup/pypy/interpreter/specialcode.py Log: change some "if isinstances" to "assert isinstances" and delete some code. now a pypy-c-fast is 2-4% faster than pypy-c-multi Modified: pypy/branch/builtin-call-speedup/pypy/interpreter/specialcode.py ============================================================================== --- pypy/branch/builtin-call-speedup/pypy/interpreter/specialcode.py (original) +++ pypy/branch/builtin-call-speedup/pypy/interpreter/specialcode.py Wed Dec 6 14:02:34 2006 @@ -8,22 +8,16 @@ from pypy.objspace.std.dictmultiobject import W_DictMultiObject w_globals = f.w_globals num = oparg >> 8 - if isinstance(w_globals, W_DictMultiObject): - w_value = w_globals.implementation.get_builtin_indexed(num) - if w_value is None: - w_builtins = f.builtin - assert isinstance(w_builtins, Module) - w_builtin_dict = w_builtins.w_dict - assert isinstance(w_builtin_dict, W_DictMultiObject) - w_value = w_builtin_dict.implementation.get_builtin_indexed(num) + assert isinstance(w_globals, W_DictMultiObject) + w_value = w_globals.implementation.get_builtin_indexed(num) + if w_value is None: + w_builtins = f.builtin + assert isinstance(w_builtins, Module) + w_builtin_dict = w_builtins.w_dict + assert isinstance(w_builtin_dict, W_DictMultiObject) + w_value = w_builtin_dict.implementation.get_builtin_indexed(num) ## if w_value is not None: ## print "CALL_LIKELY_BUILTIN fast" - else: - w_varname = f.space.wrap(OPTIMIZED_BUILTINS[num]) - w_value = f.space.finditem(f.w_globals, w_varname) - if w_value is None: - # not in the globals, now look in the built-ins - w_value = f.builtin.getdictvalue(f.space, w_varname) if w_value is None: varname = OPTIMIZED_BUILTINS[num] message = "global name '%s' is not defined" % varname From arigo at codespeak.net Wed Dec 6 14:06:08 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 6 Dec 2006 14:06:08 +0100 (CET) Subject: [pypy-svn] r35390 - in pypy/branch/jit-real-world/pypy/jit: codegen/i386 timeshifter/test Message-ID: <20061206130608.D885A10070@code0.codespeak.net> Author: arigo Date: Wed Dec 6 14:06:07 2006 New Revision: 35390 Modified: pypy/branch/jit-real-world/pypy/jit/codegen/i386/rgenop.py pypy/branch/jit-real-world/pypy/jit/timeshifter/test/test_timeshift.py Log: Fix a test. Add comments about missing operations in i386/rgenop. Skip tests trying to use floats in i386/rgenop. Modified: pypy/branch/jit-real-world/pypy/jit/codegen/i386/rgenop.py ============================================================================== --- pypy/branch/jit-real-world/pypy/jit/codegen/i386/rgenop.py (original) +++ pypy/branch/jit-real-world/pypy/jit/codegen/i386/rgenop.py Wed Dec 6 14:06:07 2006 @@ -1,4 +1,4 @@ -import sys +import sys, py from pypy.rlib.objectmodel import specialize from pypy.rpython.lltypesystem import lltype, llmemory from pypy.jit.codegen.i386.ri386 import * @@ -218,7 +218,6 @@ class Builder(GenBuilder): - def __init__(self, rgenop, mc, stackdepth): self.rgenop = rgenop self.stackdepth = stackdepth @@ -362,7 +361,7 @@ self.mc.CALL(rel32(target)) else: self.mc.CALL(gv_fnptr.operand(self)) - # XXX only for int return_kind + # XXX only for int return_kind, check calling conventions return self.returnvar(eax) def genop_same_as(self, kind, gv_x): @@ -551,13 +550,13 @@ def op_int_lshift(self, gv_x, gv_y): self.mc.MOV(eax, gv_x.operand(self)) - self.mc.MOV(ecx, gv_y.operand(self)) + self.mc.MOV(ecx, gv_y.operand(self)) # XXX check if ecx >= 32 self.mc.SHL(eax, cl) return self.returnvar(eax) def op_int_rshift(self, gv_x, gv_y): self.mc.MOV(eax, gv_x.operand(self)) - self.mc.MOV(ecx, gv_y.operand(self)) + self.mc.MOV(ecx, gv_y.operand(self)) # XXX check if ecx >= 32 self.mc.SAR(eax, cl) return self.returnvar(eax) @@ -621,7 +620,7 @@ def op_uint_rshift(self, gv_x, gv_y): self.mc.MOV(eax, gv_x.operand(self)) - self.mc.MOV(ecx, gv_y.operand(self)) + self.mc.MOV(ecx, gv_y.operand(self)) # XXX check if ecx >= 32 self.mc.SHR(eax, cl) return self.returnvar(eax) @@ -960,7 +959,7 @@ @specialize.memo() def kindToken(T): if T is lltype.Float: - raise NotImplementedError("floats in the i386 back-end") + py.test.skip("not implemented: floats in the i386 back-end") return None # for now @staticmethod Modified: pypy/branch/jit-real-world/pypy/jit/timeshifter/test/test_timeshift.py ============================================================================== --- pypy/branch/jit-real-world/pypy/jit/timeshifter/test/test_timeshift.py (original) +++ pypy/branch/jit-real-world/pypy/jit/timeshifter/test/test_timeshift.py Wed Dec 6 14:06:07 2006 @@ -688,8 +688,9 @@ s = lltype.malloc(S) s.x = 123 return s + ll_function.convert_result = lambda s: str(s.x) res = self.timeshift(ll_function, [], [], policy=P_NOVIRTUAL) - assert res.x == 123 + assert res == "123" def test_plus_minus_all_inlined(self): def ll_plus_minus(s, x, y): From arigo at codespeak.net Wed Dec 6 14:14:35 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 6 Dec 2006 14:14:35 +0100 (CET) Subject: [pypy-svn] r35391 - pypy/branch/jit-real-world/pypy/jit/timeshifter/test Message-ID: <20061206131435.81E0A10079@code0.codespeak.net> Author: arigo Date: Wed Dec 6 14:14:32 2006 New Revision: 35391 Modified: pypy/branch/jit-real-world/pypy/jit/timeshifter/test/test_timeshift.py Log: More missing convert_result. Modified: pypy/branch/jit-real-world/pypy/jit/timeshifter/test/test_timeshift.py ============================================================================== --- pypy/branch/jit-real-world/pypy/jit/timeshifter/test/test_timeshift.py (original) +++ pypy/branch/jit-real-world/pypy/jit/timeshifter/test/test_timeshift.py Wed Dec 6 14:14:32 2006 @@ -813,10 +813,10 @@ res = a, b keepalive_until_here(b) # to keep getarrayitem around return res + ll_function.convert_result = lambda x: str(len(x.item0)) res = self.timeshift(ll_function, [2], [], policy=P_NOVIRTUAL) - assert lltype.typeOf(res.item0) == lltype.Ptr(A) - assert res.item1 is None + assert res == "3" def test_red_propagate(self): S = lltype.GcStruct('S', ('n', lltype.Signed)) From arigo at codespeak.net Wed Dec 6 14:20:54 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 6 Dec 2006 14:20:54 +0100 (CET) Subject: [pypy-svn] r35392 - pypy/branch/jit-real-world/pypy/jit/timeshifter/test Message-ID: <20061206132054.3F9EC10079@code0.codespeak.net> Author: arigo Date: Wed Dec 6 14:20:53 2006 New Revision: 35392 Modified: pypy/branch/jit-real-world/pypy/jit/timeshifter/test/test_promotion.py Log: And now a missing convert_arguments. Modified: pypy/branch/jit-real-world/pypy/jit/timeshifter/test/test_promotion.py ============================================================================== --- pypy/branch/jit-real-world/pypy/jit/timeshifter/test/test_promotion.py (original) +++ pypy/branch/jit-real-world/pypy/jit/timeshifter/test/test_promotion.py Wed Dec 6 14:20:53 2006 @@ -225,6 +225,8 @@ hint(n1, concrete=True) n2 -= 1 return total + void = lambda s: None + ll_function.convert_arguments = [void, int, int, void, int] res = self.timeshift(ll_function, [None, 4, 3, None, 100], [0], policy=P_NOVIRTUAL) From arigo at codespeak.net Wed Dec 6 15:10:05 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 6 Dec 2006 15:10:05 +0100 (CET) Subject: [pypy-svn] r35394 - in pypy/dist/pypy: annotation config objspace/flow objspace/flow/test rpython tool translator translator/c translator/c/test translator/tool Message-ID: <20061206141005.DF9B310082@code0.codespeak.net> Author: arigo Date: Wed Dec 6 15:09:59 2006 New Revision: 35394 Modified: pypy/dist/pypy/annotation/policy.py pypy/dist/pypy/config/translationoption.py pypy/dist/pypy/objspace/flow/flowcontext.py pypy/dist/pypy/objspace/flow/objspace.py pypy/dist/pypy/objspace/flow/specialcase.py pypy/dist/pypy/objspace/flow/test/test_objspace.py pypy/dist/pypy/rpython/annlowlevel.py pypy/dist/pypy/tool/error.py pypy/dist/pypy/translator/c/support.py pypy/dist/pypy/translator/c/test/test_wrapping.py pypy/dist/pypy/translator/c/wrapper.py pypy/dist/pypy/translator/geninterplevel.py pypy/dist/pypy/translator/tool/raymond.py pypy/dist/pypy/translator/translator.py Log: (pedronis, arigo) Whack whack whack. 'do_imports_immediately' makes no sense as a translation config, because sub-annotations with different policies (e.g. the annlowlevel ones) must use the default True, or they crash. So move it as an annotator policy flag. But then geninterp has no annotator policy, so hack a bit more for that case. Fun fun fun. Fix some more stuff in test_wrapping and raymond. Fix c/wrapper to cope with the extra genop checks. Fix something that broke because of that. It also seems that our default gcpolicy is not refcounting any more, not sure why. Show the space operation in the "annotation degenerated to SomeObject()" message. Modified: pypy/dist/pypy/annotation/policy.py ============================================================================== --- pypy/dist/pypy/annotation/policy.py (original) +++ pypy/dist/pypy/annotation/policy.py Wed Dec 6 15:09:59 2006 @@ -29,8 +29,8 @@ def _adjust_space_config(self, space): # allow to override space options. - if getattr(self, 'override_do_imports_immediately', None) is not None: - space.do_imports_immediately = self.override_do_imports_immediately + if getattr(self, 'do_imports_immediately', None) is not None: + space.do_imports_immediately = self.do_imports_immediately class AnnotatorPolicy(BasicAnnotatorPolicy): """ Modified: pypy/dist/pypy/config/translationoption.py ============================================================================== --- pypy/dist/pypy/config/translationoption.py (original) +++ pypy/dist/pypy/config/translationoption.py Wed Dec 6 15:09:59 2006 @@ -68,8 +68,6 @@ # Flags of the TranslationContext: BoolOption("simplifying", "Simplify flow graphs", default=True), - BoolOption("do_imports_immediately", "XXX", default=True, - cmdline=None), BoolOption("builtins_can_raise_exceptions", "XXX", default=False, cmdline=None), BoolOption("list_comprehension_operations", "XXX", default=False, Modified: pypy/dist/pypy/objspace/flow/flowcontext.py ============================================================================== --- pypy/dist/pypy/objspace/flow/flowcontext.py (original) +++ pypy/dist/pypy/objspace/flow/flowcontext.py Wed Dec 6 15:09:59 2006 @@ -281,7 +281,7 @@ except OperationError, e: #print "OE", e.w_type, e.w_value - if (self.space.config.translation.do_imports_immediately and + if (self.space.do_imports_immediately and e.w_type is self.space.w_ImportError): raise ImportError('import statement always raises %s' % ( e,)) Modified: pypy/dist/pypy/objspace/flow/objspace.py ============================================================================== --- pypy/dist/pypy/objspace/flow/objspace.py (original) +++ pypy/dist/pypy/objspace/flow/objspace.py Wed Dec 6 15:09:59 2006 @@ -33,6 +33,7 @@ """ full_exceptions = False + do_imports_immediately = True def initialize(self): import __builtin__ Modified: pypy/dist/pypy/objspace/flow/specialcase.py ============================================================================== --- pypy/dist/pypy/objspace/flow/specialcase.py (original) +++ pypy/dist/pypy/objspace/flow/specialcase.py Wed Dec 6 15:09:59 2006 @@ -11,7 +11,7 @@ # import * in a function gives us the locals as Variable # we always forbid it as a SyntaxError raise SyntaxError, "RPython: import * is not allowed in functions" - if space.config.translation.do_imports_immediately: + if space.do_imports_immediately: name, glob, loc, frm = (space.unwrap(w_name), space.unwrap(w_glob), space.unwrap(w_loc), space.unwrap(w_frm)) try: Modified: pypy/dist/pypy/objspace/flow/test/test_objspace.py ============================================================================== --- pypy/dist/pypy/objspace/flow/test/test_objspace.py (original) +++ pypy/dist/pypy/objspace/flow/test/test_objspace.py Wed Dec 6 15:09:59 2006 @@ -715,7 +715,7 @@ class TestFlowObjSpaceDelay(Base): def setup_class(cls): cls.space = FlowObjSpace() - cls.space.config.translation.do_imports_immediately = False + cls.space.do_imports_immediately = False def test_import_something(self): def f(): Modified: pypy/dist/pypy/rpython/annlowlevel.py ============================================================================== --- pypy/dist/pypy/rpython/annlowlevel.py (original) +++ pypy/dist/pypy/rpython/annlowlevel.py Wed Dec 6 15:09:59 2006 @@ -34,8 +34,6 @@ class LowLevelAnnotatorPolicy(AnnotatorPolicy): allow_someobjects = False - # if this exists and is boolean, then it always wins: - override_do_imports_immediately = True def __init__(pol, rtyper=None): pol.rtyper = rtyper Modified: pypy/dist/pypy/tool/error.py ============================================================================== --- pypy/dist/pypy/tool/error.py (original) +++ pypy/dist/pypy/tool/error.py Wed Dec 6 15:09:59 2006 @@ -104,6 +104,9 @@ msg = ["annotation of %r degenerated to SomeObject()" % (what,)] if position_key is not None: graph, block, operindex = position_key + oper = block.operations[operindex] + msg.append(str(oper)) + msg.append('') msg += source_lines(graph, block, operindex, long=True) if called_from_graph is not None: Modified: pypy/dist/pypy/translator/c/support.py ============================================================================== --- pypy/dist/pypy/translator/c/support.py (original) +++ pypy/dist/pypy/translator/c/support.py Wed Dec 6 15:09:59 2006 @@ -7,6 +7,8 @@ # USESLOTS = True +PyObjPtr = lltype.Ptr(lltype.PyObject) + class ErrorValue: def __init__(self, TYPE): @@ -48,6 +50,8 @@ try: T = c.concretetype except AttributeError: + T = PyObjPtr + if T == PyObjPtr and not isinstance(c.value, lltype._ptr): return lltype.pyobjectptr(c.value) else: if T == lltype.Void: Modified: pypy/dist/pypy/translator/c/test/test_wrapping.py ============================================================================== Modified: pypy/dist/pypy/translator/c/wrapper.py ============================================================================== --- pypy/dist/pypy/translator/c/wrapper.py (original) +++ pypy/dist/pypy/translator/c/wrapper.py Wed Dec 6 15:09:59 2006 @@ -54,7 +54,7 @@ vself = Variable('self') vargs = Variable('args') vkwds = Variable('kwds') - vfname = Constant(func.func_name) + vfname = Constant(func.func_name, PyObjPtr) # avoid incref/decref on the arguments: 'self' and 'kwds' can be NULL vself.concretetype = PyObjPtr vargs.concretetype = PyObjPtr @@ -71,7 +71,7 @@ # "argument_i = decode_arg_def(fname, i, name, vargs, vkwds, default)" vlist = [vfname, inputconst(Signed, i), - Constant(varnames[i]), + Constant(varnames[i], PyObjPtr), vargs, vkwds] try: @@ -80,19 +80,19 @@ opname = 'decode_arg' else: opname = 'decode_arg_def' - vlist.append(Constant(default_value)) + vlist.append(Constant(default_value, PyObjPtr)) - v = newops.genop(opname, vlist, resulttype=Ptr(PyObject)) + v = newops.genop(opname, vlist, resulttype=PyObjPtr) #v.set_name('a', i) varguments.append(v) if vararg: # "vararg = vargs[n:]" vlist = [vargs, - Constant(nb_positional_args), - Constant(None), + Constant(nb_positional_args, PyObjPtr), + Constant(None, PyObjPtr), ] - vararg = newops.genop('getslice', vlist, resulttype=Ptr(PyObject)) + vararg = newops.genop('getslice', vlist, resulttype=PyObjPtr) #vararg.set_name('vararg', 0) varguments.append(vararg) else: @@ -172,6 +172,9 @@ newops = LowLevelOpList(translator.rtyper) callargs = graph.getargs()[:] + for v in callargs: + if not hasattr(v, 'concretetype'): + v.concretetype = PyObjPtr v_self_old = callargs.pop(0) v_self = Variable(v_self_old.name) binding = SomeInstance(clsdef) Modified: pypy/dist/pypy/translator/geninterplevel.py ============================================================================== --- pypy/dist/pypy/translator/geninterplevel.py (original) +++ pypy/dist/pypy/translator/geninterplevel.py Wed Dec 6 15:09:59 2006 @@ -1495,9 +1495,9 @@ entrypoint = dic t = TranslationContext(verbose=False, simplifying=True, - do_imports_immediately=do_imports_immediately, builtins_can_raise_exceptions=True, list_comprehension_operations=False) + t.no_annotator_but_do_imports_immediately = do_imports_immediately gen = GenRpy(t, entrypoint, modname, dic) finally: Modified: pypy/dist/pypy/translator/tool/raymond.py ============================================================================== --- pypy/dist/pypy/translator/tool/raymond.py (original) +++ pypy/dist/pypy/translator/tool/raymond.py Wed Dec 6 15:09:59 2006 @@ -3,6 +3,7 @@ from py.test import raises from pypy.rpython.extregistry import ExtRegistryEntry from pypy.annotation import model as annmodel +from pypy.annotation.policy import AnnotatorPolicy from pypy.rpython.lltypesystem import lltype from pypy.rpython import robject, rclass, rint from pypy.translator.tool.cbuild import enable_fast_compilation @@ -12,6 +13,10 @@ P = False # debug printing +class RaymondAnnotatorPolicy(AnnotatorPolicy): + allow_someobjects = True + do_imports_immediately = False + SPECIAL_METHODS = {} def setup_special_methods(): @@ -69,7 +74,7 @@ global _t # allow us to view later _t = t = TranslationContext(do_imports_immediately=False) - ann = t.buildannotator() + ann = t.buildannotator(policy=RaymondAnnotatorPolicy()) rtyper = t.buildrtyper() bk = rtyper.annotator.bookkeeper if not exports: @@ -124,7 +129,7 @@ t.viewcg() t.checkgraphs() - gcpolicy = None + gcpolicy = gc.RefcountingGcPolicy if use_boehm: gcpolicy = gc.BoehmGcPolicy @@ -132,7 +137,7 @@ if view: t.viewcg() - cbuilder = CExtModuleBuilder(t, func, gcpolicy=gcpolicy) + cbuilder = CExtModuleBuilder(t, func, config=t.config, gcpolicy=gcpolicy) # explicit build of database db = cbuilder.build_database(exports=exports, pyobj_options=pyobj_options) cbuilder.generate_source(db) Modified: pypy/dist/pypy/translator/translator.py ============================================================================== --- pypy/dist/pypy/translator/translator.py (original) +++ pypy/dist/pypy/translator/translator.py Wed Dec 6 15:09:59 2006 @@ -21,7 +21,6 @@ FLOWING_FLAGS = { 'verbose': False, 'simplifying': True, - 'do_imports_immediately': True, 'builtins_can_raise_exceptions': False, 'list_comprehension_operations': False, # True, - not super-tested } @@ -31,7 +30,7 @@ from pypy.config.pypyoption import get_pypy_config config = get_pypy_config(translating=True) # ZZZ should go away in the end - for attr in ['verbose', 'simplifying', 'do_imports_immediately', + for attr in ['verbose', 'simplifying', 'builtins_can_raise_exceptions', 'list_comprehension_operations']: if attr in flowing_flags: @@ -72,6 +71,9 @@ if self.annotator: # ZZZ self.annotator.policy._adjust_space_config(space) + elif hasattr(self, 'no_annotator_but_do_imports_immediately'): + space.do_imports_immediately = ( + self.no_annotator_but_do_imports_immediately) graph = space.build_flow(func) if self.config.translation.simplifying: simplify.simplify_graph(graph) From arigo at codespeak.net Wed Dec 6 15:31:17 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 6 Dec 2006 15:31:17 +0100 (CET) Subject: [pypy-svn] r35395 - in pypy/branch/jit-real-world/pypy: annotation objspace/flow objspace/flow/test rpython tool translator translator/c Message-ID: <20061206143117.7B77A1007C@code0.codespeak.net> Author: arigo Date: Wed Dec 6 15:31:12 2006 New Revision: 35395 Modified: pypy/branch/jit-real-world/pypy/annotation/policy.py pypy/branch/jit-real-world/pypy/objspace/flow/flowcontext.py pypy/branch/jit-real-world/pypy/objspace/flow/objspace.py pypy/branch/jit-real-world/pypy/objspace/flow/specialcase.py pypy/branch/jit-real-world/pypy/objspace/flow/test/test_objspace.py pypy/branch/jit-real-world/pypy/rpython/annlowlevel.py pypy/branch/jit-real-world/pypy/tool/error.py pypy/branch/jit-real-world/pypy/translator/c/support.py pypy/branch/jit-real-world/pypy/translator/c/wrapper.py pypy/branch/jit-real-world/pypy/translator/geninterplevel.py pypy/branch/jit-real-world/pypy/translator/translator.py Log: svn merge until r35394. Modified: pypy/branch/jit-real-world/pypy/annotation/policy.py ============================================================================== --- pypy/branch/jit-real-world/pypy/annotation/policy.py (original) +++ pypy/branch/jit-real-world/pypy/annotation/policy.py Wed Dec 6 15:31:12 2006 @@ -29,8 +29,8 @@ def _adjust_space_config(self, space): # allow to override space options. - if getattr(self, 'override_do_imports_immediately', None) is not None: - space.do_imports_immediately = self.override_do_imports_immediately + if getattr(self, 'do_imports_immediately', None) is not None: + space.do_imports_immediately = self.do_imports_immediately class AnnotatorPolicy(BasicAnnotatorPolicy): """ Modified: pypy/branch/jit-real-world/pypy/objspace/flow/flowcontext.py ============================================================================== --- pypy/branch/jit-real-world/pypy/objspace/flow/flowcontext.py (original) +++ pypy/branch/jit-real-world/pypy/objspace/flow/flowcontext.py Wed Dec 6 15:31:12 2006 @@ -287,7 +287,7 @@ except OperationError, e: #print "OE", e.w_type, e.w_value - if (self.space.config.translation.do_imports_immediately and + if (self.space.do_imports_immediately and e.w_type is self.space.w_ImportError): raise ImportError('import statement always raises %s' % ( e,)) Modified: pypy/branch/jit-real-world/pypy/objspace/flow/objspace.py ============================================================================== --- pypy/branch/jit-real-world/pypy/objspace/flow/objspace.py (original) +++ pypy/branch/jit-real-world/pypy/objspace/flow/objspace.py Wed Dec 6 15:31:12 2006 @@ -33,6 +33,7 @@ """ full_exceptions = False + do_imports_immediately = True def initialize(self): import __builtin__ Modified: pypy/branch/jit-real-world/pypy/objspace/flow/specialcase.py ============================================================================== --- pypy/branch/jit-real-world/pypy/objspace/flow/specialcase.py (original) +++ pypy/branch/jit-real-world/pypy/objspace/flow/specialcase.py Wed Dec 6 15:31:12 2006 @@ -11,7 +11,7 @@ # import * in a function gives us the locals as Variable # we always forbid it as a SyntaxError raise SyntaxError, "RPython: import * is not allowed in functions" - if space.config.translation.do_imports_immediately: + if space.do_imports_immediately: name, glob, loc, frm = (space.unwrap(w_name), space.unwrap(w_glob), space.unwrap(w_loc), space.unwrap(w_frm)) try: Modified: pypy/branch/jit-real-world/pypy/objspace/flow/test/test_objspace.py ============================================================================== --- pypy/branch/jit-real-world/pypy/objspace/flow/test/test_objspace.py (original) +++ pypy/branch/jit-real-world/pypy/objspace/flow/test/test_objspace.py Wed Dec 6 15:31:12 2006 @@ -715,7 +715,7 @@ class TestFlowObjSpaceDelay(Base): def setup_class(cls): cls.space = FlowObjSpace() - cls.space.config.translation.do_imports_immediately = False + cls.space.do_imports_immediately = False def test_import_something(self): def f(): Modified: pypy/branch/jit-real-world/pypy/rpython/annlowlevel.py ============================================================================== --- pypy/branch/jit-real-world/pypy/rpython/annlowlevel.py (original) +++ pypy/branch/jit-real-world/pypy/rpython/annlowlevel.py Wed Dec 6 15:31:12 2006 @@ -34,8 +34,6 @@ class LowLevelAnnotatorPolicy(AnnotatorPolicy): allow_someobjects = False - # if this exists and is boolean, then it always wins: - override_do_imports_immediately = True def __init__(pol, rtyper=None): pol.rtyper = rtyper Modified: pypy/branch/jit-real-world/pypy/tool/error.py ============================================================================== --- pypy/branch/jit-real-world/pypy/tool/error.py (original) +++ pypy/branch/jit-real-world/pypy/tool/error.py Wed Dec 6 15:31:12 2006 @@ -114,6 +114,9 @@ msg = ["annotation of %r degenerated to SomeObject()" % (what,)] if position_key is not None: graph, block, operindex = position_key + oper = block.operations[operindex] + msg.append(str(oper)) + msg.append('') msg += source_lines(graph, block, operindex, long=True) if called_from_graph is not None: Modified: pypy/branch/jit-real-world/pypy/translator/c/support.py ============================================================================== --- pypy/branch/jit-real-world/pypy/translator/c/support.py (original) +++ pypy/branch/jit-real-world/pypy/translator/c/support.py Wed Dec 6 15:31:12 2006 @@ -7,6 +7,8 @@ # USESLOTS = True +PyObjPtr = lltype.Ptr(lltype.PyObject) + class ErrorValue: def __init__(self, TYPE): @@ -48,6 +50,8 @@ try: T = c.concretetype except AttributeError: + T = PyObjPtr + if T == PyObjPtr and not isinstance(c.value, lltype._ptr): return lltype.pyobjectptr(c.value) else: if T == lltype.Void: Modified: pypy/branch/jit-real-world/pypy/translator/c/wrapper.py ============================================================================== --- pypy/branch/jit-real-world/pypy/translator/c/wrapper.py (original) +++ pypy/branch/jit-real-world/pypy/translator/c/wrapper.py Wed Dec 6 15:31:12 2006 @@ -54,7 +54,7 @@ vself = Variable('self') vargs = Variable('args') vkwds = Variable('kwds') - vfname = Constant(func.func_name) + vfname = Constant(func.func_name, PyObjPtr) # avoid incref/decref on the arguments: 'self' and 'kwds' can be NULL vself.concretetype = PyObjPtr vargs.concretetype = PyObjPtr @@ -71,7 +71,7 @@ # "argument_i = decode_arg_def(fname, i, name, vargs, vkwds, default)" vlist = [vfname, inputconst(Signed, i), - Constant(varnames[i]), + Constant(varnames[i], PyObjPtr), vargs, vkwds] try: @@ -80,19 +80,19 @@ opname = 'decode_arg' else: opname = 'decode_arg_def' - vlist.append(Constant(default_value)) + vlist.append(Constant(default_value, PyObjPtr)) - v = newops.genop(opname, vlist, resulttype=Ptr(PyObject)) + v = newops.genop(opname, vlist, resulttype=PyObjPtr) #v.set_name('a', i) varguments.append(v) if vararg: # "vararg = vargs[n:]" vlist = [vargs, - Constant(nb_positional_args), - Constant(None), + Constant(nb_positional_args, PyObjPtr), + Constant(None, PyObjPtr), ] - vararg = newops.genop('getslice', vlist, resulttype=Ptr(PyObject)) + vararg = newops.genop('getslice', vlist, resulttype=PyObjPtr) #vararg.set_name('vararg', 0) varguments.append(vararg) else: @@ -172,6 +172,9 @@ newops = LowLevelOpList(translator.rtyper) callargs = graph.getargs()[:] + for v in callargs: + if not hasattr(v, 'concretetype'): + v.concretetype = PyObjPtr v_self_old = callargs.pop(0) v_self = Variable(v_self_old.name) binding = SomeInstance(clsdef) Modified: pypy/branch/jit-real-world/pypy/translator/geninterplevel.py ============================================================================== --- pypy/branch/jit-real-world/pypy/translator/geninterplevel.py (original) +++ pypy/branch/jit-real-world/pypy/translator/geninterplevel.py Wed Dec 6 15:31:12 2006 @@ -1495,9 +1495,9 @@ entrypoint = dic t = TranslationContext(verbose=False, simplifying=True, - do_imports_immediately=do_imports_immediately, builtins_can_raise_exceptions=True, list_comprehension_operations=False) + t.no_annotator_but_do_imports_immediately = do_imports_immediately gen = GenRpy(t, entrypoint, modname, dic) finally: Modified: pypy/branch/jit-real-world/pypy/translator/translator.py ============================================================================== --- pypy/branch/jit-real-world/pypy/translator/translator.py (original) +++ pypy/branch/jit-real-world/pypy/translator/translator.py Wed Dec 6 15:31:12 2006 @@ -19,7 +19,6 @@ FLOWING_FLAGS = { 'verbose': False, 'simplifying': True, - 'do_imports_immediately': True, 'builtins_can_raise_exceptions': False, 'list_comprehension_operations': False, # True, - not super-tested } @@ -30,7 +29,7 @@ from pypy.config.pypyoption import pypy_optiondescription config = Config(pypy_optiondescription) # ZZZ should go away in the end - for attr in ['verbose', 'simplifying', 'do_imports_immediately', + for attr in ['verbose', 'simplifying', 'builtins_can_raise_exceptions', 'list_comprehension_operations']: if attr in flowing_flags: @@ -59,6 +58,9 @@ if self.annotator: # ZZZ self.annotator.policy._adjust_space_config(space) + elif hasattr(self, 'no_annotator_but_do_imports_immediately'): + space.do_imports_immediately = ( + self.no_annotator_but_do_imports_immediately) graph = space.build_flow(func) if self.config.translation.simplifying: simplify.simplify_graph(graph) From mwh at codespeak.net Wed Dec 6 15:33:04 2006 From: mwh at codespeak.net (mwh at codespeak.net) Date: Wed, 6 Dec 2006 15:33:04 +0100 (CET) Subject: [pypy-svn] r35396 - in pypy/dist/pypy/rpython: . lltypesystem Message-ID: <20061206143304.5D4F91007C@code0.codespeak.net> Author: mwh Date: Wed Dec 6 15:33:01 2006 New Revision: 35396 Modified: pypy/dist/pypy/rpython/lltypesystem/rpbc.py pypy/dist/pypy/rpython/rpbc.py Log: first cut at trying to represent small (<4) sets of functions as indexes into an array. Modified: pypy/dist/pypy/rpython/lltypesystem/rpbc.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/rpbc.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/rpbc.py Wed Dec 6 15:33:01 2006 @@ -4,15 +4,15 @@ from pypy.annotation import model as annmodel from pypy.objspace.flow.model import Constant, Variable from pypy.rpython.lltypesystem.lltype import \ - typeOf, Void, ForwardReference, Struct, Bool, \ - Ptr, malloc, nullptr + typeOf, Void, ForwardReference, Struct, Bool, Char, \ + Ptr, malloc, nullptr, Array, Signed from pypy.rpython.rmodel import Repr, TyperError, inputconst, inputdesc from pypy.rpython.rpbc import samesig,\ commonbase, allattributenames, adjust_shape, \ AbstractClassesPBCRepr, AbstractMethodsPBCRepr, OverriddenFunctionPBCRepr, \ AbstractMultipleFrozenPBCRepr, MethodOfFrozenPBCRepr, \ AbstractFunctionsPBCRepr, AbstractMultipleUnrelatedFrozenPBCRepr, \ - SingleFrozenPBCRepr, none_frozen_pbc_repr + SingleFrozenPBCRepr, none_frozen_pbc_repr, get_concrete_calltable from pypy.rpython.lltypesystem import rclass, llmemory from pypy.tool.sourcetools import has_varargs @@ -112,7 +112,108 @@ def get_specfunc_row(self, llop, v, c_rowname, resulttype): return llop.genop('getfield', [v, c_rowname], resulttype=resulttype) - + +class SmallFunctionSetPBCRepr(Repr): + def __init__(self, rtyper, s_pbc): + self.rtyper = rtyper + self.s_pbc = s_pbc + self.callfamily = s_pbc.descriptions.iterkeys().next().getcallfamily() + concretetable, uniquerows = get_concrete_calltable(self.rtyper, + self.callfamily) + assert len(uniquerows) == 1 + self.lowleveltype = Char + self.pointer_repr = FunctionsPBCRepr(rtyper, s_pbc) + self.descriptions = list(s_pbc.descriptions) + if self.s_pbc.can_be_None: + self.descriptions.insert(0, None) + + def _setup_repr(self): + POINTER_TABLE = Array(self.pointer_repr.lowleveltype) + pointer_table = malloc(POINTER_TABLE, len(self.descriptions), + immortal=True) + for i, desc in enumerate(self.descriptions): + pointer_table[i] = self.pointer_repr.convert_desc(desc) + self.c_pointer_table = inputconst(Ptr(POINTER_TABLE), pointer_table) + + def get_s_callable(self): + return self.s_pbc + + def get_r_implfunc(self): + return self, 0 + + def get_s_signatures(self, shape): + funcdesc = self.s_pbc.descriptions.iterkeys().next() + return funcdesc.get_s_signatures(shape) + + def convert_desc(self, funcdesc): + return chr(self.descriptions.index(funcdesc)) + + def convert_const(self, value): + if isinstance(value, types.MethodType) and value.im_self is None: + value = value.im_func # unbound method -> bare function + if value is None: + return chr(0) + funcdesc = self.rtyper.annotator.bookkeeper.getdesc(value) + return self.convert_desc(funcdesc) + +## def convert_to_concrete_llfn(self, v, shape, index, llop): +## return v + + def rtype_simple_call(self, hop): + v_index = hop.inputarg(self, arg=0) + v_ptr = hop.llops.convertvar(v_index, self, self.pointer_repr) + hop2 = hop.copy() + hop2.args_r[0] = self.pointer_repr + hop2.args_v[0] = v_ptr + return hop2.dispatch() + + rtype_call_args = rtype_simple_call + +class __extend__(pairtype(SmallFunctionSetPBCRepr, FunctionsPBCRepr)): + def convert_from_to((r_set, r_ptr), v, llops): + if r_ptr.lowleveltype is Void: + wrapper = HalfConcreteWrapper(r_ptr.get_unique_llfn) + return inputconst(Void, wrapper) + else: + v_int = llops.genop('cast_char_to_int', [v], + resulttype=Signed) + return llops.genop('getarrayitem', [r_set.c_pointer_table, v_int], + resulttype=r_ptr.lowleveltype) + +class __extend__(pairtype(FunctionsPBCRepr, SmallFunctionSetPBCRepr)): + def convert_from_to((r_ptr, r_set), v, llops): + assert r_ptr.lowleveltype is Void + desc, = r_ptr.s_pbc.descriptions + return inputconst(Char, r_set.convert_desc(desc)) + +_conversion_tables = {} +def conversion_table(r_from, r_to): + key = r_from, r_to + if key in _conversion_tables: + return _conversion_tables[key] + else: + t = malloc(Array(Char), len(r_from.descriptions), immortal=True) + l = [] + for i, d in enumerate(r_from.descriptions): + j = r_to.descriptions.index(d) + l.append(j) + t[i] = chr(j) + if l == range(len(r_from.descriptions)): + r = None + else: + r = inputconst(Ptr(Array(Char)), t) + _conversion_tables[key] = r + return r + +class __extend__(pairtype(SmallFunctionSetPBCRepr, SmallFunctionSetPBCRepr)): + def convert_from_to((r_from, r_to), v, llops): + c_table = conversion_table(r_from, r_to) + if c_table: + return llops.genop('getarrayitem', [c_table, v], + resulttype=lltype.Char) + else: + return v + class MethodsPBCRepr(AbstractMethodsPBCRepr): """Representation selected for a PBC of the form {func: classdef...}. It assumes that all the methods come from the same name in a base @@ -128,7 +229,8 @@ r_class = self.r_im_self.rclass mangled_name, r_func = r_class.clsfields[self.methodname] assert isinstance(r_func, (FunctionsPBCRepr, - OverriddenFunctionPBCRepr)) + OverriddenFunctionPBCRepr, + SmallFunctionSetPBCRepr)) # s_func = r_func.s_pbc -- not precise enough, see # test_precise_method_call_1. Build a more precise one... funcdescs = [desc.funcdesc for desc in hop.args_s[0].descriptions] Modified: pypy/dist/pypy/rpython/rpbc.py ============================================================================== --- pypy/dist/pypy/rpython/rpbc.py (original) +++ pypy/dist/pypy/rpython/rpbc.py Wed Dec 6 15:33:01 2006 @@ -27,6 +27,13 @@ getRepr = OverriddenFunctionPBCRepr else: getRepr = rtyper.type_system.rpbc.FunctionsPBCRepr + if rtyper.getconfig().translation.withsmallfuncsets and \ + 1 < len(self.descriptions) < 4 and \ + hasattr(rtyper.type_system.rpbc, 'SmallFunctionSetPBCRepr'): + callfamily = self.descriptions.iterkeys().next().getcallfamily() + concretetable, uniquerows = get_concrete_calltable(rtyper, callfamily) + if len(uniquerows) == 1: + getRepr = rtyper.type_system.rpbc.SmallFunctionSetPBCRepr else: getRepr = getFrozenPBCRepr elif issubclass(kind, description.ClassDesc): From mwh at codespeak.net Wed Dec 6 15:40:34 2006 From: mwh at codespeak.net (mwh at codespeak.net) Date: Wed, 6 Dec 2006 15:40:34 +0100 (CET) Subject: [pypy-svn] r35397 - pypy/dist/pypy/config Message-ID: <20061206144034.E939110087@code0.codespeak.net> Author: mwh Date: Wed Dec 6 15:40:33 2006 New Revision: 35397 Modified: pypy/dist/pypy/config/translationoption.py Log: argh, forgot this Modified: pypy/dist/pypy/config/translationoption.py ============================================================================== --- pypy/dist/pypy/config/translationoption.py (original) +++ pypy/dist/pypy/config/translationoption.py Wed Dec 6 15:40:33 2006 @@ -36,6 +36,8 @@ cmdline="-d --debug", default=False), BoolOption("insist", "Try hard to go on RTyping", default=False, cmdline="--insist"), + BoolOption("withsmallfuncsets", "Represent small groups of functions as small integers", + default=False), BoolOption("countmallocs", "Count mallocs and frees", default=False, cmdline=None), From cfbolz at codespeak.net Wed Dec 6 16:17:36 2006 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Wed, 6 Dec 2006 16:17:36 +0100 (CET) Subject: [pypy-svn] r35398 - pypy/dist/pypy/module/posix Message-ID: <20061206151736.6FAF51007C@code0.codespeak.net> Author: cfbolz Date: Wed Dec 6 16:17:35 2006 New Revision: 35398 Modified: pypy/dist/pypy/module/posix/__init__.py Log: remove execve from posix when translating to an ootype backend: execve is fundamentally lltype specific, currently. Modified: pypy/dist/pypy/module/posix/__init__.py ============================================================================== --- pypy/dist/pypy/module/posix/__init__.py (original) +++ pypy/dist/pypy/module/posix/__init__.py Wed Dec 6 16:17:35 2006 @@ -77,6 +77,13 @@ #if hasattr(ctypes_posix, 'uname'): # interpleveldefs['uname'] = 'interp_posix.uname' + def setup_after_space_initialization(self): + """NOT_RPYTHON""" + space = self.space + config = space.config + # XXX execve does not work under ootypesystem yet :-( + if config.translating and config.typesystem != "lltype": + space.delattr(self, space.wrap("execve")) for constant in dir(os): value = getattr(os, constant) From antocuni at codespeak.net Wed Dec 6 16:24:29 2006 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Wed, 6 Dec 2006 16:24:29 +0100 (CET) Subject: [pypy-svn] r35399 - pypy/dist/pypy/module/posix Message-ID: <20061206152429.02FF01007C@code0.codespeak.net> Author: antocuni Date: Wed Dec 6 16:24:28 2006 New Revision: 35399 Modified: pypy/dist/pypy/module/posix/__init__.py Log: typo Modified: pypy/dist/pypy/module/posix/__init__.py ============================================================================== --- pypy/dist/pypy/module/posix/__init__.py (original) +++ pypy/dist/pypy/module/posix/__init__.py Wed Dec 6 16:24:28 2006 @@ -82,7 +82,7 @@ space = self.space config = space.config # XXX execve does not work under ootypesystem yet :-( - if config.translating and config.typesystem != "lltype": + if config.translating and config.translation.type_system != "lltype": space.delattr(self, space.wrap("execve")) for constant in dir(os): From cfbolz at codespeak.net Wed Dec 6 16:33:18 2006 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Wed, 6 Dec 2006 16:33:18 +0100 (CET) Subject: [pypy-svn] r35401 - pypy/dist/pypy/config Message-ID: <20061206153318.4C01510087@code0.codespeak.net> Author: cfbolz Date: Wed Dec 6 16:33:17 2006 New Revision: 35401 Modified: pypy/dist/pypy/config/translationoption.py Log: make refcounting the default gc (which is true for py.test only, translate.py overrides this default to be the boehm gc). Modified: pypy/dist/pypy/config/translationoption.py ============================================================================== --- pypy/dist/pypy/config/translationoption.py (original) +++ pypy/dist/pypy/config/translationoption.py Wed Dec 6 16:33:17 2006 @@ -26,7 +26,7 @@ ChoiceOption("gc", "Garbage Collection Strategy", ["boehm", "ref", "framework", "none", "stacklessgc", "exact_boehm"], - "boehm", requires={ + "ref", requires={ "stacklessgc": [("translation.stackless", True)]}, cmdline="--gc"), BoolOption("thread", "enable use of threading primitives", From santagada at codespeak.net Wed Dec 6 17:34:21 2006 From: santagada at codespeak.net (santagada at codespeak.net) Date: Wed, 6 Dec 2006 17:34:21 +0100 (CET) Subject: [pypy-svn] r35402 - in pypy/dist/pypy/lang/js: . test Message-ID: <20061206163421.4960D10075@code0.codespeak.net> Author: santagada Date: Wed Dec 6 17:34:09 2006 New Revision: 35402 Modified: pypy/dist/pypy/lang/js/interpreter.py pypy/dist/pypy/lang/js/jsobj.py pypy/dist/pypy/lang/js/test/test_interp.py Log: re-implemented the abstract relational comparison and added some more examples... I still have to finish comparing strings. Modified: pypy/dist/pypy/lang/js/interpreter.py ============================================================================== --- pypy/dist/pypy/lang/js/interpreter.py (original) +++ pypy/dist/pypy/lang/js/interpreter.py Wed Dec 6 17:34:09 2006 @@ -2,7 +2,7 @@ from pypy.lang.js.astgen import * from pypy.lang.js.context import ExecutionContext from pypy.lang.js.jsobj import W_Number, W_String, W_Object -from pypy.lang.js.jsobj import w_Undefined, W_Arguments, W_Boolean +from pypy.lang.js.jsobj import w_Undefined, W_Arguments, W_Boolean, NaN from pypy.lang.js.scope import scope_manager def writer(x): @@ -118,26 +118,44 @@ def call(self, context = None): return self.expr.call(context) -def AbstractRelationalLt(value1, value2): - # TODO: really implement the algorithm - v1 = value1.ToPrimitive().ToNumber() - v2 = value2.ToPrimitive().ToNumber() - return v10)"),["true"]) self.assert_prints(parse_d("print(0>1)"),["false"]) + self.assert_prints(parse_d("print(0>0)"),["false"]) + self.assert_prints(parse_d("print(1<0)"),["false"]) + self.assert_prints(parse_d("print(0<1)"),["true"]) + self.assert_prints(parse_d("print(0<0)"),["false"]) + def test_while(self): self.assert_prints(parse_d(""" From antocuni at codespeak.net Wed Dec 6 18:15:56 2006 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Wed, 6 Dec 2006 18:15:56 +0100 (CET) Subject: [pypy-svn] r35404 - pypy/dist/pypy/translator Message-ID: <20061206171556.4375D1007B@code0.codespeak.net> Author: antocuni Date: Wed Dec 6 18:15:54 2006 New Revision: 35404 Modified: pypy/dist/pypy/translator/driver.py Log: Copy the .NET executable in the goal dir after the compilation. Modified: pypy/dist/pypy/translator/driver.py ============================================================================== --- pypy/dist/pypy/translator/driver.py (original) +++ pypy/dist/pypy/translator/driver.py Wed Dec 6 18:15:54 2006 @@ -581,9 +581,32 @@ unpatch(*self.old_cli_defs) self.log.info("Compiled %s" % filename) + if self.standalone: + self.copy_cli_exe() task_compile_cli = taskdef(task_compile_cli, ['source_cli'], 'Compiling CLI source') + def copy_cli_exe(self): + # XXX messy + import os.path + import shutil + main_exe = self.c_entryp._exe + usession_path, main_exe_name = os.path.split(main_exe) + pypylib_dll = os.path.join(usession_path, 'pypylib.dll') + + shutil.copy(main_exe, '.') + shutil.copy(pypylib_dll, '.') + newexename = self.exe_name % self.get_info() + if '/' not in newexename and '\\' not in newexename: + newexename = './' + newexename + f = file(newexename, 'w') + f.write("""#!/bin/bash +cd `dirname $0` # XXX doesn't work if it's placed in PATH +mono "%s" "$@" +""" % main_exe_name) + f.close() + os.chmod(newexename, 0755) + def task_run_cli(self): pass task_run_cli = taskdef(task_run_cli, ['compile_cli'], From santagada at codespeak.net Wed Dec 6 21:04:43 2006 From: santagada at codespeak.net (santagada at codespeak.net) Date: Wed, 6 Dec 2006 21:04:43 +0100 (CET) Subject: [pypy-svn] r35410 - in pypy/dist/pypy/lang/js: . test Message-ID: <20061206200443.6A2E910077@code0.codespeak.net> Author: santagada Date: Wed Dec 6 21:04:23 2006 New Revision: 35410 Modified: pypy/dist/pypy/lang/js/astgen.py pypy/dist/pypy/lang/js/interpreter.py pypy/dist/pypy/lang/js/parser.py pypy/dist/pypy/lang/js/test/test_interp.py Log: starting to make the support for named functions Modified: pypy/dist/pypy/lang/js/astgen.py ============================================================================== --- pypy/dist/pypy/lang/js/astgen.py (original) +++ pypy/dist/pypy/lang/js/astgen.py Wed Dec 6 21:04:23 2006 @@ -6,6 +6,7 @@ class Node(object): __metaclass__ = extendabletype + # TODO Add line info for debug # def __init__(self, lineno = 1): # self.lineno = lineno @@ -46,12 +47,11 @@ self.right = right class Function(Node): - def __init__(self, params, body, scope): + def __init__(self, name, params, body, scope): + self.name = name self.params = params self.body = body self.scope = scope - #w_obj = W_Object({}, function=self) - #self.scope = Scope(copy(scope.dict)) class Group(Node): def __init__(self, expr): @@ -107,7 +107,10 @@ class Script(Node): def __init__(self, nodes, var_decl, func_decl): self.nodes = nodes + import pdb + #pdb.set_trace() [scope_manager.add_variable(id.name, w_Undefined) for id in var_decl] + [scope_manager.add_variable(id.name, id) for id in func_decl] self.var_decl = var_decl self.func_decl = func_decl @@ -173,13 +176,14 @@ elif tp == 'DOT': return Dot(from_dict(d['0']), from_dict(d['1'])) elif tp == 'FUNCTION': + name = d['name'] scope = scope_manager.enter_scope() body = from_dict(d['body']) if d['params'] == '': params = [] else: params = d['params'].split(',') - f = Function(params, body, scope) + f = Function(name, params, body, scope) scope_manager.leave_scope() return f elif tp == 'GROUP': @@ -219,11 +223,16 @@ return Return(from_dict(d['value'])) elif tp == 'SCRIPT': # TODO: get function names + if isinstance(d['funDecls'], dict): + func_decl = [from_dict(d['funDecls']),] + else: + func_decl = [from_dict(x) for x in d['funDecls']] + if isinstance(d['varDecls'], dict): var_decl = [from_dict(d['varDecls']),] else: var_decl = [from_dict(x) for x in d['varDecls']] - return Script(getlist(d), var_decl, []) + return Script(getlist(d), var_decl, func_decl) elif tp == 'SEMICOLON': return Semicolon(from_dict(d['expression'])) elif tp == 'STRING': Modified: pypy/dist/pypy/lang/js/interpreter.py ============================================================================== --- pypy/dist/pypy/lang/js/interpreter.py (original) +++ pypy/dist/pypy/lang/js/interpreter.py Wed Dec 6 21:04:23 2006 @@ -114,7 +114,6 @@ return self.elsePart.call(context) class __extend__(Group): - """The __extend__ class.""" def call(self, context = None): return self.expr.call(context) @@ -123,6 +122,7 @@ Implements the Abstract Relational Comparison x < y Still not 100% to the spec """ + # TODO complete the funcion with strings comparison s1 = x.ToPrimitive('Number') s2 = y.ToPrimitive('Number') if not (isinstance(s1, W_String) and isinstance(s2, W_String)): Modified: pypy/dist/pypy/lang/js/parser.py ============================================================================== --- pypy/dist/pypy/lang/js/parser.py (original) +++ pypy/dist/pypy/lang/js/parser.py Wed Dec 6 21:04:23 2006 @@ -2,7 +2,8 @@ """ Using narcisus to generate code """ -# 1st attempt - exec the code +# FIXME Rename this file (overwrite the std python lib) +# TODO Should be replaced by a real parser import os import py Modified: pypy/dist/pypy/lang/js/test/test_interp.py ============================================================================== --- pypy/dist/pypy/lang/js/test/test_interp.py (original) +++ pypy/dist/pypy/lang/js/test/test_interp.py Wed Dec 6 21:04:23 2006 @@ -252,4 +252,12 @@ self.assert_prints(parse_d(""" var x;x=3; print(x)"""), ["3"]) + def test_fun_decl(self): + py.test.skip("still not ready") + self.assert_prints(parse_d(""" + function x () { print('i work')} + x() + """), ["i work"]) + + From mwh at codespeak.net Wed Dec 6 23:02:22 2006 From: mwh at codespeak.net (mwh at codespeak.net) Date: Wed, 6 Dec 2006 23:02:22 +0100 (CET) Subject: [pypy-svn] r35411 - pypy/dist/pypy/rpython/lltypesystem Message-ID: <20061206220222.472261007B@code0.codespeak.net> Author: mwh Date: Wed Dec 6 23:02:20 2006 New Revision: 35411 Modified: pypy/dist/pypy/rpython/lltypesystem/rpbc.py Log: further hacking around the SmallFunctionSetRepr. still gives a crashing pypy-c though :/ Modified: pypy/dist/pypy/rpython/lltypesystem/rpbc.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/rpbc.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/rpbc.py Wed Dec 6 23:02:20 2006 @@ -175,6 +175,7 @@ wrapper = HalfConcreteWrapper(r_ptr.get_unique_llfn) return inputconst(Void, wrapper) else: + assert v.concretetype is Char v_int = llops.genop('cast_char_to_int', [v], resulttype=Signed) return llops.genop('getarrayitem', [r_set.c_pointer_table, v_int], @@ -245,6 +246,16 @@ opname = 'call_args' hop2.v_s_insertfirstarg(v_func, s_func) # insert 'function' + + if type(hop2.args_r[0]) != type(r_func): # XXX argh... + if type(hop2.args_r[0]) is SmallFunctionSetPBCRepr: + assert type(r_func) is FunctionsPBCRepr + hop2.args_r[0] = FunctionsPBCRepr(self.rtyper, s_func) + else: + assert type(r_func) is SmallFunctionSetPBCRepr + assert type(hop2.args_r[0]) is FunctionsPBCRepr + # this is actually ok, i think... + # now hop2 looks like simple_call(function, self, args...) return hop2.dispatch(opname=opname) From ale at codespeak.net Thu Dec 7 07:53:18 2006 From: ale at codespeak.net (ale at codespeak.net) Date: Thu, 7 Dec 2006 07:53:18 +0100 (CET) Subject: [pypy-svn] r35412 - pypy/dist/pypy/doc Message-ID: <20061207065318.757B910071@code0.codespeak.net> Author: ale Date: Thu Dec 7 07:53:15 2006 New Revision: 35412 Modified: pypy/dist/pypy/doc/pyontology.txt Log: Update to documentation Modified: pypy/dist/pypy/doc/pyontology.txt ============================================================================== --- pypy/dist/pypy/doc/pyontology.txt (original) +++ pypy/dist/pypy/doc/pyontology.txt Thu Dec 7 07:53:15 2006 @@ -5,6 +5,39 @@ .. contents:: .. sectnum:: +Prerequisites +============== + +The Ontology reasoner uses the following python packages: + + Logilab constraint solver: logilab.org + The RDFlib package: rdflib.net + The PyParsing package: + +Usage +====== + +To read an ontology into the reasoner, the Ontology class has to be instantiated. When instantiated the ontology cna be read by supplying the ontology file to the "add_file" method. To convert the ontology into a constraint satisfaction problem, the "attach_fd" method should be called. + + O = Ontology() + O.add_file() + O.attach_fd() + +Now consistency can be checked by calling the "consistency" method. + +A SPARQL query can be answered by calling the "sparql" method with a query string. If the query string is not valid, a ParserException will be raised. If the query leads to an inconsinstent problem a ConsistencyFailure exceptionis raised. + + O.consistency() + query = """ + PREFIX ns: + SELECT ?x + WHERE { + ?x ns:p 123 . + }""" + res = O.sparql(query) + +The return value of the sparql methhod is a list of dictionaries, one dictionary for each solution to the query. The dictionary maps query variables to values. + Introduction ============= @@ -23,8 +56,10 @@ 5. the union of two or more class descriptions (unionOf predicate) 6. the complement of a class description (complementOf predicate) +In case 2 the class is final, ie there can be no more or no less members than the enumeration gives. + Properties ----------- +----------- Properties can be of the types owl:ObjectProperty, owl:DatatypeProperty, owl:FunctionalProperty, owl: InverseFunctionalProperty, owl:SymmetricProperty. @@ -56,6 +91,26 @@ Some special variables and domains are created to enable to infer facts on Ontologies that have no individuals. +Class hierarchy +----------------- + +The class hierarchy for OWL DL ontologies is: + +Classes that contains individuals + + ClassDomain + / \ + ThingDomain PropertyDomain + +There some special instances of these classes. Owl_Thing contains all indivuals, "owl_Class" contains all classes, "rdf_Property" contains all Properties,"owl_Restriction" contains all restriction classes. + +Type +------ + +A "rdf:type" triple links a Urirefence to either +There can be more than one triple, for a subject, containing the predicate "rdf:Type". +These type declarations need to checked and possibly merged. If a class is final (ie. defined be enumerationg its instances) we cannot add more instances the the class. If we meet a typedeclaration foran individual we shall check if it is part off the existing definition. If we meet a typedeclaration for a class, we need to merge the class extension of the new definition with the old definition. + Restrictions ------------ @@ -97,7 +152,12 @@ The equivalentClass states that the subject class and object class contain the same elements. -If the two classes has a different number of elements it must mean that all elements must be the same. +The implementation of these semantics has to consider different situations. + + 1. The two classes are final. In this case the classes cannot be narrowed by the semantics of equivalentClass. We have to prove that the two classes have the same members. So we check the number of members in the two classes. + If the number of elements differ the only way that the two classes can be equivalent is if all members are the same. + If the numbers of elements are equal we try to prove equality between the individuals of the classes + The Ontology class @@ -105,6 +165,7 @@ ClassDomain.finish() +++++++++++++++++++++ + 1. Evaluate the uninitialised constraints of the class. sadsda From ale at codespeak.net Thu Dec 7 08:01:11 2006 From: ale at codespeak.net (ale at codespeak.net) Date: Thu, 7 Dec 2006 08:01:11 +0100 (CET) Subject: [pypy-svn] r35413 - in pypy/dist/pypy/lib/pyontology: . test Message-ID: <20061207070111.B73CE10071@code0.codespeak.net> Author: ale Date: Thu Dec 7 08:01:04 2006 New Revision: 35413 Modified: pypy/dist/pypy/lib/pyontology/constraint_classes.py pypy/dist/pypy/lib/pyontology/pyontology.py pypy/dist/pypy/lib/pyontology/sparql_grammar.py pypy/dist/pypy/lib/pyontology/test/test_ontology.py pypy/dist/pypy/lib/pyontology/test/test_sparql.py pypy/dist/pypy/lib/pyontology/test/testont.rdf pypy/dist/pypy/lib/pyontology/test/testont2.rdf Log: Bugfixes, different approach to xml types Modified: pypy/dist/pypy/lib/pyontology/constraint_classes.py ============================================================================== --- pypy/dist/pypy/lib/pyontology/constraint_classes.py (original) +++ pypy/dist/pypy/lib/pyontology/constraint_classes.py Thu Dec 7 08:01:04 2006 @@ -248,7 +248,6 @@ keep.append(key) sub.removeValues([v for v in sub.getValues() if not v in keep]) -import time class PropertyConstrain3(AbstractConstraint): cost = 1 def __init__(self, prop, variable, cls_or_restriction): @@ -345,14 +344,15 @@ class EquivalentPropertyConstraint(SubClassConstraint): - cost = 100 + cost = 10 def narrow(self, domains): subdom = domains[self.variable] superdom = domains[self.object] - for value in subdom.getValues(): - if not value in superdom: - superdom.addValue(value[0], value[1]) + superset = set(superdom.getValues()) + superset = superset.union(set(subdom.getValues())) + superdom.setValues(superset) + subdom.setValues(superset) class TypeConstraint(SubClassConstraint): cost = 1 @@ -367,6 +367,7 @@ class FunctionalCardinality(OwlConstraint): """Contraint: all values must be distinct""" + cost = 100 def narrow(self, domains): """narrowing algorithm for the constraint""" Modified: pypy/dist/pypy/lib/pyontology/pyontology.py ============================================================================== --- pypy/dist/pypy/lib/pyontology/pyontology.py (original) +++ pypy/dist/pypy/lib/pyontology/pyontology.py Thu Dec 7 08:01:04 2006 @@ -425,8 +425,10 @@ def Types(typ): class Type(Literal): def __contains__(self, item): - #assert isinstance(item, rdflib_literal) - return item.datatype is None or item.datatype == self.Type + if isinstance(item, rdflib_literal): + return item.datatype is None or item.datatype == self.Type + else: + return XMLTypes[self.Type.split("#")[-1]] == type(item) datatype = Type datatype.Type = typ @@ -455,9 +457,9 @@ getUriref('rdf', 'Literal') : Literal, # getUriref('rdf', 'type') : Property, } -XMLTypes = ['string', 'float', 'integer', 'date'] -#XMLTypes = {'string': str, 'float': float, 'integer': int, -# 'date': lambda x: datetime.date(*[int(v) for v in x.split('-')])} +#XMLTypes = ['string', 'float', 'integer', 'date'] +XMLTypes = {'string': str, 'float': float, 'integer': int, + 'date': lambda x: datetime.date(*[int(v) for v in x.split('-')])} for typ in XMLTypes: uri = getUriref('xmlschema', typ) @@ -546,7 +548,11 @@ trip_ = [trip.Subject[0], trip.Verb[0], trip.Object[0]] for item in trip_: if isinstance(item[0], rdflib_literal): - newtrip.append(item[0]) + o = item[0] + if o.datatype in builtin_voc: + o = XMLTypes[o.datatype.split('#')[-1]](o) + self.variables['owl_Literal'].addValue(o) + newtrip.append(o) elif item[0].NCNAME_PREFIX: uri = prefixes[item[0].NCNAME_PREFIX[0]] + item[0].NCNAME[0] newtrip.append(URIRef(uri)) @@ -706,9 +712,9 @@ val = v.uri else: val = v - d[k] = unicode(val) + d[k] = (val) if k in query_vars: - res_dict[query_vars[k]] = unicode(val) + res_dict[query_vars[k]] = (val) res.append(res_dict) return res @@ -743,10 +749,9 @@ else: val = Individual(obj, o) elif type(o) == rdflib_literal: - print "Literal type", repr(o.datatype) +# self.variables.setdefault('owl_Literal', ClassDomain('owl_Literal',u'')) if o.datatype in builtin_voc: - print "XML datatype" - o = XMLTypes[o.datatype.split('#')[-1]](o) + o = XMLTypes[o.datatype.split('#')[-1]](o) self.variables['owl_Literal'].addValue(o) val = o else: Modified: pypy/dist/pypy/lib/pyontology/sparql_grammar.py ============================================================================== --- pypy/dist/pypy/lib/pyontology/sparql_grammar.py (original) +++ pypy/dist/pypy/lib/pyontology/sparql_grammar.py Thu Dec 7 08:01:04 2006 @@ -24,7 +24,7 @@ return o def replace_int(s, loc, toks): - return [rdfliteral(int(toks[0]), datatype="http://www.w3.org/2001/XMLSchema#int")] + return [rdfliteral(int(toks[0]), datatype="http://www.w3.org/2001/XMLSchema#integer")] def replace_string(s, loc, toks): @@ -590,5 +590,7 @@ # NCNAME ::= ( "_" | NCCHAR1 ) ((NCCHAR|".")* NCCHAR)? - NCNAME << ("_" | NCCHAR1) + NCNAME << ("_" | NCCHAR1) + Optional(ZeroOrMore(NCCHAR | ".") + NCCHAR) + + Modified: pypy/dist/pypy/lib/pyontology/test/test_ontology.py ============================================================================== --- pypy/dist/pypy/lib/pyontology/test/test_ontology.py (original) +++ pypy/dist/pypy/lib/pyontology/test/test_ontology.py Thu Dec 7 08:01:04 2006 @@ -35,7 +35,6 @@ raises(ConsistencyFailure, O.consistency) def test_XMLSchema_string(): - py.test.skip("WIP") O = Ontology() a = URIRef(u'A') p = URIRef(u'P') @@ -47,7 +46,7 @@ O.consistency() def test_XMLSchema_string_fail(): - py.test.skip("WIP") +# py.test.skip("WIP") O = Ontology() a = URIRef(u'A') p = URIRef(u'P') Modified: pypy/dist/pypy/lib/pyontology/test/test_sparql.py ============================================================================== --- pypy/dist/pypy/lib/pyontology/test/test_sparql.py (original) +++ pypy/dist/pypy/lib/pyontology/test/test_sparql.py Thu Dec 7 08:01:04 2006 @@ -118,7 +118,7 @@ O.attach_fd() O.finish() res = O.sparql(query) - assert res[0]['x'] == '123' + assert res[0]['x'] == 123 def test_case_4(): """ search for s in p """ @@ -145,7 +145,7 @@ res = O.sparql(query) assert res[0]['x'] == u'http://example.org/ns#sub' - assert res[0]['y'] == u'123' + assert res[0]['y'] == 123 assert res[0]['x'] == u'http://example.org/ns#sub' def test_case_6(): @@ -164,7 +164,6 @@ def test_case_7(): """ for all p's return p[1] if p[0]==s """ - #py.test.skip("Doesn't work yet due to changed generatorinterface") query = qt_proto % ('?x ?y ?z', '?x ?y ?z .') O = Ontology() @@ -174,7 +173,16 @@ res = O.sparql(query) assert list(O.variables['query_x_'].getValues())[0].uri == u'http://example.org/ns#sub' assert res[0]['x'] == u'http://example.org/ns#sub' - + +def test_filter(): + query = qt_proto % ('?x ?y', '?x ns:p ?y .\n FILTER(?y < 124) .') + O = Ontology() + O.add_file("testont.rdf") + O.attach_fd() + O.finish() + res = O.sparql(query) + assert res[0]['y'] == 123 + query1 = """ PREFIX ltw : PREFIX owl : @@ -190,13 +198,12 @@ query2 = """ PREFIX ltw : PREFIX owl : - SELECT ?project + SELECT ?project ?date_begin WHERE { ?project ltw:funded_by ltw:BMBF . ?project ltw:dateStart ?date_begin . ?project ltw:dateEnd ?date_end . - FILTER ( ?date_begin < 2007 ) . - FILTER ( ?date_end >= 2006) . + FILTER ( ?date_begin < 2007 && ?date_end >= 2006) . }""" #which project is funded in a technological area (i.e. Semantic web), query3 = """ @@ -220,7 +227,7 @@ assert res[0]['person'] == u'\nKlara Vicsi' def test_query2(): - py.test.skip("Doesn't work yet") +# py.test.skip("Doesn't work yet") O = Ontology() O.add_file("testont2.rdf") O.attach_fd() @@ -228,8 +235,20 @@ res = O.sparql(query2) assert len(res) == 1 assert res[0]['activity'] == u'http://www.lt-world.org/ltw.owl#obj_59754' + assert res[0]['person'] == u'\nKlara Vicsi' + +def test_query3(): + #py.test.skip("Doesn't work yet") + O = Ontology() + O.add_file("testont2.rdf") + O.attach_fd() + + res = O.sparql(query3) + assert len(res) == 1 + assert res[0]['activity'] == u'http://www.lt-world.org/ltw.owl#obj_59754' assert res[0]['person'] == u'\nKlara Vicsi' + import xmlrpclib, socket, os, signal class TestXMLRPC: @@ -258,4 +277,6 @@ print "test_xmlrpc" server = xmlrpclib.ServerProxy("http://localhost:9000", allow_none=True) result = server.sparql(qt_proto % ('?x', 'ns:sub ns:p ?x .')) - assert result[0]['x'] == '123' + result2 = server.sparql(qt_proto % ('?x', 'ns:test ns:p ?x .')) + print "Result 2",result2 + assert result[0]['x'] == 123 Modified: pypy/dist/pypy/lib/pyontology/test/testont.rdf ============================================================================== --- pypy/dist/pypy/lib/pyontology/test/testont.rdf (original) +++ pypy/dist/pypy/lib/pyontology/test/testont.rdf Thu Dec 7 08:01:04 2006 @@ -11,7 +11,7 @@ 123 + "http://www.w3.org/2001/XMLSchema#integer">123 Modified: pypy/dist/pypy/lib/pyontology/test/testont2.rdf ============================================================================== --- pypy/dist/pypy/lib/pyontology/test/testont2.rdf (original) +++ pypy/dist/pypy/lib/pyontology/test/testont2.rdf Thu Dec 7 08:01:04 2006 @@ -32,9 +32,9 @@ joseph.dichy at univ-lyon2.fr NLP!Natural Language Processing!MT - + 2000-08-01 - + 1998-02-01 http://www.hltcentral.org/projects From cfbolz at codespeak.net Thu Dec 7 08:53:56 2006 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Thu, 7 Dec 2006 08:53:56 +0100 (CET) Subject: [pypy-svn] r35414 - pypy/dist/pypy/doc Message-ID: <20061207075356.8961510071@code0.codespeak.net> Author: cfbolz Date: Thu Dec 7 08:53:55 2006 New Revision: 35414 Modified: pypy/dist/pypy/doc/pyontology.txt Log: fix rest, fix some typos, reindent Modified: pypy/dist/pypy/doc/pyontology.txt ============================================================================== --- pypy/dist/pypy/doc/pyontology.txt (original) +++ pypy/dist/pypy/doc/pyontology.txt Thu Dec 7 08:53:55 2006 @@ -17,7 +17,10 @@ Usage ====== -To read an ontology into the reasoner, the Ontology class has to be instantiated. When instantiated the ontology cna be read by supplying the ontology file to the "add_file" method. To convert the ontology into a constraint satisfaction problem, the "attach_fd" method should be called. +To read an ontology into the reasoner, the Ontology class has to be +instantiated. When instantiated the ontology cna be read by supplying the +ontology file to the "add_file" method. To convert the ontology into a +constraint satisfaction problem, the "attach_fd" method should be called:: O = Ontology() O.add_file() @@ -25,7 +28,10 @@ Now consistency can be checked by calling the "consistency" method. -A SPARQL query can be answered by calling the "sparql" method with a query string. If the query string is not valid, a ParserException will be raised. If the query leads to an inconsinstent problem a ConsistencyFailure exceptionis raised. +A SPARQL query can be answered by calling the "sparql" method with a query +string. If the query string is not valid, a ParserException will be raised. If +the query leads to an inconsinstent problem a ConsistencyFailure exceptionis +raised:: O.consistency() query = """ @@ -36,7 +42,8 @@ }""" res = O.sparql(query) -The return value of the sparql methhod is a list of dictionaries, one dictionary for each solution to the query. The dictionary maps query variables to values. +The return value of the sparql method is a list of dictionaries, one dictionary +for each solution to the query. The dictionary maps query variables to values. Introduction ============= @@ -61,11 +68,12 @@ Properties ----------- -Properties can be of the types owl:ObjectProperty, owl:DatatypeProperty, owl:FunctionalProperty, -owl: InverseFunctionalProperty, owl:SymmetricProperty. +Properties can be of the types owl:ObjectProperty, owl:DatatypeProperty, +owl:FunctionalProperty, owl: InverseFunctionalProperty, owl:SymmetricProperty. -Properties can have restrictions on them, either value restrictions, cardinality restrictions or global -restrictions in the form of domain and range restrictions. +Properties can have restrictions on them, either value restrictions, +cardinality restrictions or global restrictions in the form of domain and range +restrictions. Individuals @@ -77,88 +85,135 @@ Implementation =============== -The Ontology is read from a file (either in RDF-XML or N3 format) into a RDFLIB Graph. The triples of the -Graph are considered individually by calling the methods on the Ontology class. +The Ontology is read from a file (either in RDF-XML or N3 format) into a RDFLIB +Graph. The triples of the Graph are considered individually by calling the +methods on the Ontology class. + +Since the ordering of triples is random the final processing has to be +postponed until all triples have been considered. + +When all triples have been processed the semantics of the Ontology will be +contained in the objects in self.variables. In order to complete the conversion +from the OWL ontology to a constraint problem the finish method of the objects +needs to be called. + +The result of considering all the triples is a constraint problem. A constraint +problem cosists of variables domains an constraints. The variables of the OWL +constraint problem are the names of the userdefined classses and userdefined +properties. Each variable has a domain which hold the individuals. The +constraints makes relations between variables. By setting the domain of each +variables, which have an empty domain (meaningthat it have no explicit +individuals) to the domain of everything (owl:Thing or owl:Property for +properties) the constraints can narrow the domain to the subset that satisfies +the constraints imposed on this class. + +The domains of properties contain tuples of individual and value, so the triple +(Peter, hasParent, Mary) will put the tuple (Peter, Mary) into the domain of +the property hasParent. -Since the ordering of triples is random the final processing has to be postponed until all triples have been -considered. - -When all triples have been processed the semantics of the Ontology will be contained in the objects in self.variables. In order to complete the conversion from the OWL ontology to a constraint problem the finish method of the objects needs to be called. - -The result of considering all the triples is a constraint problem. A constraint problem cosists of variables domains an constraints. The variables of the OWL constraint problem are the names of the userdefined classses and userdefined properties. Each variable has a domain which hold the individuals. The constraints makes relations between variables. By setting the domain of each variables, which have an empty domain (meaningthat it have no explicit individuals) to the domain of everything (owl:Thing or owl:Property for properties) the constraints can narrow the domain to the subset that satisfies the constraints imposed on this class. - -The domains of properties contain tuples of individual and value, so the triple (Peter, hasParent, Mary) will put the tuple (Peter, Mary) into the domain of the property hasParent. - -Some special variables and domains are created to enable to infer facts on Ontologies that have no individuals. +Some special variables and domains are created to enable to infer facts on +Ontologies that have no individuals. Class hierarchy ----------------- The class hierarchy for OWL DL ontologies is: -Classes that contains individuals +Classes that contains individuals:: ClassDomain / \ ThingDomain PropertyDomain -There some special instances of these classes. Owl_Thing contains all indivuals, "owl_Class" contains all classes, "rdf_Property" contains all Properties,"owl_Restriction" contains all restriction classes. +There some special instances of these classes. Owl_Thing contains all +indivuals, "owl_Class" contains all classes, "rdf_Property" contains all +Properties,"owl_Restriction" contains all restriction classes. Type ------ -A "rdf:type" triple links a Urirefence to either -There can be more than one triple, for a subject, containing the predicate "rdf:Type". -These type declarations need to checked and possibly merged. If a class is final (ie. defined be enumerationg its instances) we cannot add more instances the the class. If we meet a typedeclaration foran individual we shall check if it is part off the existing definition. If we meet a typedeclaration for a class, we need to merge the class extension of the new definition with the old definition. +A "rdf:type" triple links a Urirefence to either There can be more than one +triple, for a subject, containing the predicate "rdf:Type". These type +declarations need to checked and possibly merged. If a class is final (ie. +defined be enumerationg its instances) we cannot add more instances the the +class. If we meet a typedeclaration foran individual we shall check if it is +part off the existing definition. If we meet a typedeclaration for a class, we +need to merge the class extension of the new definition with the old +definition. Restrictions ------------ -Restrictions are anonymous classes that define restrictions on properties. The individuals that satisfies The restriction are the Individuals that shall be in the domain of this anonymous class. +Restrictions are anonymous classes that define restrictions on properties. The +individuals that satisfies The restriction are the Individuals that shall be in +the domain of this anonymous class. Cardinality restrictions ------------------------ -Cardinality restrictions have two implications. The can be used to assert the restrictions on individuals, -to check that an individual of class fulfills the restriction, and to check the schema of a class is consistent. -That is to check for example that a certain class is not defined to have a maxCardinality lower than a -minCardinality for a certain property. +Cardinality restrictions have two implications. The can be used to assert the +restrictions on individuals, to check that an individual of class fulfills the +restriction, and to check the schema of a class is consistent. That is to +check for example that a certain class is not defined to have a maxCardinality +lower than a minCardinality for a certain property. maxCardinality -------------- -The result of a maxCardinality restriction is all the individuals that have at most the number of values for the property as stated in the object of the triple. - -This is achieved by adding a constraint that will use the "getValuesPrKey" method of the property domain and remove the individuals that do not satisfy the constraint from the domain of the restriction. The constraint is implementedby the class CardinalityConstraint, which takes a property class, a restriction name, a val and a comparison string (can be '<','>' or '='). - -To check for the consistency in absence of individuals, a special variable is created with the domain of range(val + 1). This is the domain of possible values for the cardinality. - -As the name of the property might not be known when the triple containing the cardinality restriction is being processed the actual addition of the domains and constraint is being deferred to the finish method of the restriction class. +The result of a maxCardinality restriction is all the individuals that have at +most the number of values for the property as stated in the object of the +triple. + +This is achieved by adding a constraint that will use the "getValuesPrKey" +method of the property domain and remove the individuals that do not satisfy +the constraint from the domain of the restriction. The constraint is +implementedby the class CardinalityConstraint, which takes a property class, a +restriction name, a val and a comparison string (can be '<','>' or '='). + +To check for the consistency in absence of individuals, a special variable is +created with the domain of range(val + 1). This is the domain of possible +values for the cardinality. + +As the name of the property might not be known when the triple containing the +cardinality restriction is being processed the actual addition of the domains +and constraint is being deferred to the finish method of the restriction class. hasValue -------- -The hasvalue restriction defines the set of individuals which have the value for the property concerned. +The hasvalue restriction defines the set of individuals which have the value +for the property concerned. subClassOf ---------- -The subClassOf triple states that the set of individuals of the subject class shall be a subset of the setof individuals of the object class. +The subClassOf triple states that the set of individuals of the subject class +shall be a subset of the setof individuals of the object class. -When a triple with predicate "subClassOf" is considered, we add the object to the bases attribute of the subjecct class. When the finish method is called the domains and constraints of the subject class will be augmented with those of the object class. +When a triple with predicate "subClassOf" is considered, we add the object to +the bases attribute of the subjecct class. When the finish method is called the +domains and constraints of the subject class will be augmented with those of +the object class. equivalentClass ---------------- -The equivalentClass states that the subject class and object class contain the same elements. +The equivalentClass states that the subject class and object class contain the +same elements. The implementation of these semantics has to consider different situations. - 1. The two classes are final. In this case the classes cannot be narrowed by the semantics of equivalentClass. We have to prove that the two classes have the same members. So we check the number of members in the two classes. - If the number of elements differ the only way that the two classes can be equivalent is if all members are the same. - If the numbers of elements are equal we try to prove equality between the individuals of the classes - + 1. The two classes are final. In this case the classes cannot be + narrowed by the semantics of equivalentClass. We have to prove that the + two classes have the same members. So we check the number of members in + the two classes. + 2. If the number of elements differ the only way that the two classes + can be equivalent is if all members are the same. + + 3. If the numbers of elements are equal we try to prove equality between + the individuals of the classes + The Ontology class ------------------- @@ -167,10 +222,9 @@ +++++++++++++++++++++ 1. Evaluate the uninitialised constraints of the class. - sadsda 2. Loop through the bases list and for each class: - call finish() - instantiate the constraints found in the baseclasses - remove BNodes from the domain store + call finish() + instantiate the constraints found in the baseclasses + remove BNodes from the domain store From cfbolz at codespeak.net Thu Dec 7 09:08:19 2006 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Thu, 7 Dec 2006 09:08:19 +0100 (CET) Subject: [pypy-svn] r35416 - pypy/dist/pypy/rpython/memory/gctransform/test Message-ID: <20061207080819.BCA0A10080@code0.codespeak.net> Author: cfbolz Date: Thu Dec 7 09:08:17 2006 New Revision: 35416 Modified: pypy/dist/pypy/rpython/memory/gctransform/test/test_refcounting.py pypy/dist/pypy/rpython/memory/gctransform/test/test_stacklessframework.py Log: two more problems Modified: pypy/dist/pypy/rpython/memory/gctransform/test/test_refcounting.py ============================================================================== --- pypy/dist/pypy/rpython/memory/gctransform/test/test_refcounting.py (original) +++ pypy/dist/pypy/rpython/memory/gctransform/test/test_refcounting.py Thu Dec 7 09:08:17 2006 @@ -14,7 +14,7 @@ from pypy.translator.c import gc t = rtype(f, args_s) - cbuild = CStandaloneBuilder(t, f, gcpolicy=RefcountingGcPolicy2) + cbuild = CStandaloneBuilder(t, f, t.config, gcpolicy=RefcountingGcPolicy2) db = cbuild.generate_graphs_for_llinterp() graph = cbuild.getentrypointptr()._obj.graph llinterp = LLInterpreter(t.rtyper) Modified: pypy/dist/pypy/rpython/memory/gctransform/test/test_stacklessframework.py ============================================================================== --- pypy/dist/pypy/rpython/memory/gctransform/test/test_stacklessframework.py (original) +++ pypy/dist/pypy/rpython/memory/gctransform/test/test_stacklessframework.py Thu Dec 7 09:08:17 2006 @@ -27,7 +27,7 @@ from pypy.annotation.listdef import s_list_of_strings t = rtype(entrypoint, [s_list_of_strings]) - cbuild = CStandaloneBuilder(t, entrypoint, + cbuild = CStandaloneBuilder(t, entrypoint, t.config, gcpolicy=StacklessFrameworkGcPolicy2) db = cbuild.generate_graphs_for_llinterp() entrypointptr = cbuild.getentrypointptr() From mwh at codespeak.net Thu Dec 7 10:38:28 2006 From: mwh at codespeak.net (mwh at codespeak.net) Date: Thu, 7 Dec 2006 10:38:28 +0100 (CET) Subject: [pypy-svn] r35417 - pypy/dist/pypy/rpython/lltypesystem Message-ID: <20061207093828.99C3B10071@code0.codespeak.net> Author: mwh Date: Thu Dec 7 10:38:26 2006 New Revision: 35417 Modified: pypy/dist/pypy/rpython/lltypesystem/rpbc.py Log: argh, more conversion hacking. don't assume that SomePBC(subset) has the same lowleveltype as SomePBC(set) in method calling. this is likely to be rather inefficient, some kind of SomePBC(subset of that SomePBC) notion would be better. Modified: pypy/dist/pypy/rpython/lltypesystem/rpbc.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/rpbc.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/rpbc.py Thu Dec 7 10:38:26 2006 @@ -6,7 +6,7 @@ from pypy.rpython.lltypesystem.lltype import \ typeOf, Void, ForwardReference, Struct, Bool, Char, \ Ptr, malloc, nullptr, Array, Signed -from pypy.rpython.rmodel import Repr, TyperError, inputconst, inputdesc +from pypy.rpython.rmodel import Repr, TyperError, inputconst, inputdesc, HalfConcreteWrapper from pypy.rpython.rpbc import samesig,\ commonbase, allattributenames, adjust_shape, \ AbstractClassesPBCRepr, AbstractMethodsPBCRepr, OverriddenFunctionPBCRepr, \ @@ -196,9 +196,12 @@ t = malloc(Array(Char), len(r_from.descriptions), immortal=True) l = [] for i, d in enumerate(r_from.descriptions): - j = r_to.descriptions.index(d) - l.append(j) - t[i] = chr(j) + if d in r_to.descriptions: + j = r_to.descriptions.index(d) + l.append(j) + t[i] = chr(j) + else: + l.append(None) if l == range(len(r_from.descriptions)): r = None else: @@ -211,7 +214,7 @@ c_table = conversion_table(r_from, r_to) if c_table: return llops.genop('getarrayitem', [c_table, v], - resulttype=lltype.Char) + resulttype=Char) else: return v @@ -247,14 +250,10 @@ hop2.v_s_insertfirstarg(v_func, s_func) # insert 'function' - if type(hop2.args_r[0]) != type(r_func): # XXX argh... - if type(hop2.args_r[0]) is SmallFunctionSetPBCRepr: - assert type(r_func) is FunctionsPBCRepr - hop2.args_r[0] = FunctionsPBCRepr(self.rtyper, s_func) - else: - assert type(r_func) is SmallFunctionSetPBCRepr - assert type(hop2.args_r[0]) is FunctionsPBCRepr - # this is actually ok, i think... + if type(hop2.args_r[0]) is SmallFunctionSetPBCRepr and type(r_func) is FunctionsPBCRepr: + hop2.args_r[0] = FunctionsPBCRepr(self.rtyper, s_func) + else: + hop2.args_v[0] = hop2.llops.convertvar(hop2.args_v[0], r_func, hop2.args_r[0]) # now hop2 looks like simple_call(function, self, args...) return hop2.dispatch(opname=opname) From ericvrp at codespeak.net Thu Dec 7 10:53:12 2006 From: ericvrp at codespeak.net (ericvrp at codespeak.net) Date: Thu, 7 Dec 2006 10:53:12 +0100 (CET) Subject: [pypy-svn] r35418 - in pypy/dist/pypy/jit/codegen/llvm: . lib test Message-ID: <20061207095312.D257810079@code0.codespeak.net> Author: ericvrp Date: Thu Dec 7 10:53:09 2006 New Revision: 35418 Modified: pypy/dist/pypy/jit/codegen/llvm/lib/libllvmjit.cpp pypy/dist/pypy/jit/codegen/llvm/lib/libllvmjit.h pypy/dist/pypy/jit/codegen/llvm/llvmjit.py pypy/dist/pypy/jit/codegen/llvm/test/test_llvmjit.py Log: llvmjit... * Improved error message with parse errors. * drop passnames parameter from llvmjit.transform() in favor of an optLevel parameter. Modified: pypy/dist/pypy/jit/codegen/llvm/lib/libllvmjit.cpp ============================================================================== --- pypy/dist/pypy/jit/codegen/llvm/lib/libllvmjit.cpp (original) +++ pypy/dist/pypy/jit/codegen/llvm/lib/libllvmjit.cpp Thu Dec 7 10:53:09 2006 @@ -21,8 +21,9 @@ #include "llvm/Support/PassNameParser.h" #include "llvm/Assembly/PrintModulePass.h" //for PrintModulePass #include "llvm/Analysis/Verifier.h" //for createVerifierPass +#include "llvm/Analysis/LoadValueNumbering.h" //for createLoadValueNumberingPass #include "llvm/Transforms/Scalar.h" //for createInstructionCombiningPass... - +#include "llvm/Transforms/IPO.h" //for createGlobalDCEPass,createIPConstantPropagationPass,createFunctionInliningPass,createConstantMergePass #include "llvm/Target/TargetOptions.h" //for PrintMachineCode #include @@ -32,12 +33,8 @@ using namespace llvm; -Module* gp_module; // = new Module("llvmjit"); -ExecutionEngine* gp_execution_engine; // = ExecutionEngine::create(new ExistingModuleProvider(gp_module), false); - -//all optimization/transform passes -//static cl::list -// PassList(cl::desc("Optimizations available:")); +Module* gp_module; +ExecutionEngine* gp_execution_engine; //some global data for the tests to play with int g_data; @@ -56,29 +53,100 @@ } -int transform(const char* passnames) { +int transform(int optLevel) { //optlevel [0123] if (!gp_module) { return -1; } - PassManager passes; //XXX: note: if passnames is the same as last time we can reuse passes - passes.add(new TargetData(gp_module)); + //XXX we should also provide transforms on function level - //XXX next couple of passes should be dependent on passnames! - passes.add(new PrintModulePass()); - passes.add(createInstructionCombiningPass()); + //note: see llvm/projects/Stacker/lib/compiler/StackerCompiler.cpp for a good pass-list + + PassManager passes; + passes.add(new TargetData(gp_module)); // some passes need this as a first pass + passes.add(createVerifierPass()); // Make sure we start with a good graph + //passes.add(new PrintModulePass()); // Visual feedback + + if (optLevel >= 1) { + // Clean up disgusting code + passes.add(createCFGSimplificationPass()); + // Remove unused globals + passes.add(createGlobalDCEPass()); + // IP Constant Propagation + passes.add(createIPConstantPropagationPass()); + // Clean up after IPCP + passes.add(createInstructionCombiningPass()); + // Clean up after IPCP + passes.add(createCFGSimplificationPass()); + // Inline small definitions (functions) + passes.add(createFunctionInliningPass()); + // Simplify cfg by copying code + passes.add(createTailDuplicationPass()); + if (optLevel >= 2) { + // Merge & remove BBs + passes.add(createCFGSimplificationPass()); + // Compile silly sequences + passes.add(createInstructionCombiningPass()); + // Reassociate expressions + passes.add(createReassociatePass()); + // Combine silly seq's + passes.add(createInstructionCombiningPass()); + // Eliminate tail calls + passes.add(createTailCallEliminationPass()); + // Merge & remove BBs + passes.add(createCFGSimplificationPass()); + // Hoist loop invariants + passes.add(createLICMPass()); + // Clean up after the unroller + passes.add(createInstructionCombiningPass()); + // Canonicalize indvars + passes.add(createIndVarSimplifyPass()); + // Unroll small loops + passes.add(createLoopUnrollPass()); + // Clean up after the unroller + passes.add(createInstructionCombiningPass()); + // GVN for load instructions + passes.add(createLoadValueNumberingPass()); + // Remove common subexprs + passes.add(createGCSEPass()); + // Constant prop with SCCP + passes.add(createSCCPPass()); + } + if (optLevel >= 3) { + // Run instcombine again after redundancy elimination + passes.add(createInstructionCombiningPass()); + // Delete dead stores + passes.add(createDeadStoreEliminationPass()); + // SSA based 'Aggressive DCE' + passes.add(createAggressiveDCEPass()); + // Merge & remove BBs + passes.add(createCFGSimplificationPass()); + // Merge dup global constants + passes.add(createConstantMergePass()); + } + } + + // Merge & remove BBs passes.add(createCFGSimplificationPass()); - passes.add(new PrintModulePass()); + // Memory To Register + passes.add(createPromoteMemoryToRegisterPass()); + // Compile silly sequences + passes.add(createInstructionCombiningPass()); + // Make sure everything is still good. passes.add(createVerifierPass()); + //passes.add(new PrintModulePass()); // Visual feedback return passes.run(*gp_module); } int parse(const char* llsource) { - Module* module = ParseAssemblyString(llsource, gp_module); + ParseError parse_error; + Module* module = ParseAssemblyString(llsource, gp_module, &parse_error); if (!module) { - std::cerr << "Can not parse:\n" << llsource << "\n" << std::flush; + int line, col; + parse_error.getErrorLocation(line, col); + std::cerr << "Parse error:\n" << llsource << "\n" << "Error: " << parse_error.getRawMessage() << ":" << line << "," << col << "\n" << std::flush; return false; } Modified: pypy/dist/pypy/jit/codegen/llvm/lib/libllvmjit.h ============================================================================== --- pypy/dist/pypy/jit/codegen/llvm/lib/libllvmjit.h (original) +++ pypy/dist/pypy/jit/codegen/llvm/lib/libllvmjit.h Thu Dec 7 10:53:09 2006 @@ -5,7 +5,7 @@ #endif void restart(); -int transform(const char* passnames); +int transform(int optlevel); int parse(const char* llsource); //Function code Modified: pypy/dist/pypy/jit/codegen/llvm/llvmjit.py ============================================================================== --- pypy/dist/pypy/jit/codegen/llvm/llvmjit.py (original) +++ pypy/dist/pypy/jit/codegen/llvm/llvmjit.py Thu Dec 7 10:53:09 2006 @@ -52,7 +52,7 @@ transform = llvmjit.transform transform.restype = c_int -transform.argtypes = [c_char_p] +transform.argtypes = [c_int] parse = llvmjit.parse parse.restype = c_int Modified: pypy/dist/pypy/jit/codegen/llvm/test/test_llvmjit.py ============================================================================== --- pypy/dist/pypy/jit/codegen/llvm/test/test_llvmjit.py (original) +++ pypy/dist/pypy/jit/codegen/llvm/test/test_llvmjit.py Thu Dec 7 10:53:09 2006 @@ -1,13 +1,7 @@ import py from sys import platform from os.path import dirname, join - -try: - from pypy.translator.c.test.test_genc import compile - import_error = False #XXX temporary HACK until problem solves itself. -except AttributeError: #AttributeError: Values instance has no attribute 'gcpolicy' - import_error = True #pypy/translator/c/test/test_genc.py:289 - +from pypy.translator.c.test.test_genc import compile from pypy.jit.codegen.llvm import llvmjit try: @@ -206,14 +200,9 @@ llvmjit.parse(lldeadcode) deadcode = llvmjit.getNamedFunction('deadcode') assert llvmjit.execute(deadcode, 10) == 10 * 2 - - #XXX enable this part of the test asap - #assert not llvmjit.transform("instcombine printm verify") + assert llvmjit.transform(3) #optlevel = [0123] assert llvmjit.execute(deadcode, 20) == 20 * 2 - assert llvmjit.transform("instcombine simplifycfg printm verify") - assert llvmjit.execute(deadcode, 30) == 30 * 2 - def test_modify_global_data(): llvmjit.restart() llvmjit.set_global_data(10) @@ -248,8 +237,6 @@ pass def test_execute_translation(): #put this one last because it takes the most time - if import_error: - py.test.skip("import error") if platform == 'darwin': py.test.skip('dynamic vs. static library issue on Darwin. see: http://www.cocoadev.com/index.pl?ApplicationLinkingIssues for more information (FIXME)') From afayolle at codespeak.net Thu Dec 7 11:02:58 2006 From: afayolle at codespeak.net (afayolle at codespeak.net) Date: Thu, 7 Dec 2006 11:02:58 +0100 (CET) Subject: [pypy-svn] r35419 - in pypy/dist/pypy/tool/build: . bin Message-ID: <20061207100258.92BA310079@code0.codespeak.net> Author: afayolle Date: Thu Dec 7 11:02:55 2006 New Revision: 35419 Modified: pypy/dist/pypy/tool/build/bin/client pypy/dist/pypy/tool/build/client.py Log: Moved some code from bin/client to client.py Dropped ChannelWrapper, because ZipFile calls g.tell() and I could not figure how to emulate that. Fixed other zip related bugs. Note: I get a zip, but it does not contain pypy-c, I'll look into this. Modified: pypy/dist/pypy/tool/build/bin/client ============================================================================== --- pypy/dist/pypy/tool/build/bin/client (original) +++ pypy/dist/pypy/tool/build/bin/client Thu Dec 7 11:02:55 2006 @@ -5,34 +5,28 @@ import path import sys import random -from pypy.tool.build import config +from pypy.tool.build import config as buildconfig from py.execnet import SshGateway, PopenGateway -from pypy.tool.build.client import init +from pypy.tool.build.client import init, zip_result from pypy.config.config import to_optparse, Config from pypy.config import pypyoption from pypy.translator.goal import targetpypystandalone from pypy.translator.driver import TranslationDriver from pypy.tool.udir import udir -from zipfile import ZipFile -if config.server in ['localhost', '127.0.0.1']: +if buildconfig.server in ['localhost', '127.0.0.1']: gw = PopenGateway() else: - gw = SshGateway(config.server) -channel = init(gw, config.system_config, path=config.path, - port=config.port) - -class ChannelWrapper(object): - def __init__(self, channel): - self.channel = channel - - def write(self, data): - self.channel.send(data) + gw = SshGateway(buildconfig.server) + +channel = init(gw, + buildconfig.system_config, + path=buildconfig.path, + port=buildconfig.port) + - def close(self): - self.channel.send(None) print channel.receive() # welcome message try: @@ -59,12 +53,8 @@ default_goal='compile') driver.proceed(['compile']) - channelwrapper = ChannelWrapper(channel) - zip = ZipFile(channelwrapper, 'w') - for fpath in udir.visit(): - zip.writestr(fpath.relto(udir), fpath.read()) - zip.close() - + zip_result(udir, channel) + print 'done with compilation, waiting for next' except EOFError: sys.exit() Modified: pypy/dist/pypy/tool/build/client.py ============================================================================== --- pypy/dist/pypy/tool/build/client.py (original) +++ pypy/dist/pypy/tool/build/client.py Thu Dec 7 11:02:55 2006 @@ -1,5 +1,8 @@ -import time import thread +import py +from zipfile import ZipFile +from cStringIO import StringIO + class PPBClient(object): def __init__(self, channel, sysinfo, testing=False): @@ -76,7 +79,6 @@ """ def init(gw, sysconfig, path=None, port=12321, testing=False): from pypy.tool.build import execnetconference - from pypy.tool.build import server from pypy.config.config import make_dict if path is None: @@ -86,3 +88,18 @@ conference = execnetconference.conference(gw, port, False) channel = conference.remote_exec(initcode % (path, sysinfo, testing)) return channel + +def zip_result(res_dir, channel): + # channelwrapper = ChannelWrapper(channel) + buf = StringIO() + zip = ZipFile(buf, 'w') + for fpath in res_dir.visit(): + try: + zip.writestr(fpath.relto(res_dir), fpath.read()) + except (py.error.ENOENT, py.error.EISDIR), exc: + print exc + continue + zip.close() + channel.send(buf.getvalue()) + channel.send(None) + From antocuni at codespeak.net Thu Dec 7 11:29:03 2006 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Thu, 7 Dec 2006 11:29:03 +0100 (CET) Subject: [pypy-svn] r35420 - pypy/dist/pypy/translator/goal Message-ID: <20061207102903.9EEEC1007C@code0.codespeak.net> Author: antocuni Date: Thu Dec 7 11:29:02 2006 New Revision: 35420 Modified: pypy/dist/pypy/translator/goal/bench-cronjob.py Log: Add pypy.net to the list of automatically-built pypys. Modified: pypy/dist/pypy/translator/goal/bench-cronjob.py ============================================================================== --- pypy/dist/pypy/translator/goal/bench-cronjob.py (original) +++ pypy/dist/pypy/translator/goal/bench-cronjob.py Thu Dec 7 11:29:02 2006 @@ -174,6 +174,7 @@ c--profopt='-c "from richards import *;main(iterations=1)"' c--_objspace-std-withstrdict--profopt='-c "from richards import *;main(iterations=1)"' c--gc=framework--_objspace-std-withstrdict--profopt='-c "from richards import *;main(iterations=1)"' + cli """.split('\n') if backend.strip() and not backend.strip().startswith('#')] print time.ctime() for backend in backends: From ericvrp at codespeak.net Thu Dec 7 11:58:31 2006 From: ericvrp at codespeak.net (ericvrp at codespeak.net) Date: Thu, 7 Dec 2006 11:58:31 +0100 (CET) Subject: [pypy-svn] r35421 - in pypy/dist/pypy/jit/codegen/llvm: . lib test Message-ID: <20061207105831.CEF6E10084@code0.codespeak.net> Author: ericvrp Date: Thu Dec 7 11:58:29 2006 New Revision: 35421 Modified: pypy/dist/pypy/jit/codegen/llvm/lib/libllvmjit.cpp pypy/dist/pypy/jit/codegen/llvm/rgenop.py pypy/dist/pypy/jit/codegen/llvm/test/test_rgenop.py Log: llvmjit rgenop intermediate checkin Modified: pypy/dist/pypy/jit/codegen/llvm/lib/libllvmjit.cpp ============================================================================== --- pypy/dist/pypy/jit/codegen/llvm/lib/libllvmjit.cpp (original) +++ pypy/dist/pypy/jit/codegen/llvm/lib/libllvmjit.cpp Thu Dec 7 11:58:29 2006 @@ -146,7 +146,7 @@ if (!module) { int line, col; parse_error.getErrorLocation(line, col); - std::cerr << "Parse error:\n" << llsource << "\n" << "Error: " << parse_error.getRawMessage() << ":" << line << "," << col << "\n" << std::flush; + std::cerr << "\n" << llsource << "\n" << "Error: " << parse_error.getRawMessage() << ":" << line << "," << col << "\n" << std::flush; return false; } Modified: pypy/dist/pypy/jit/codegen/llvm/rgenop.py ============================================================================== --- pypy/dist/pypy/jit/codegen/llvm/rgenop.py (original) +++ pypy/dist/pypy/jit/codegen/llvm/rgenop.py Thu Dec 7 11:58:29 2006 @@ -76,12 +76,19 @@ #repr? +n_labels = [0] + class Label(GenLabel): - def __init__(self, startaddr, arg_positions, stackdepth): - self.startaddr = startaddr - self.arg_positions = arg_positions - self.stackdepth = stackdepth + def __init__(self): + self.label = n_labels[0] + n_labels[0] += 1 + + def operand(self): + return 'label %%L%d' % self.label + + def operand2(self): + return 'L%d:' % self.label class FlexSwitch(CodeGenSwitch): @@ -175,6 +182,8 @@ def __init__(self, rgenop): self.rgenop = rgenop self.asm = [] #list of llvm assembly source code lines + self.label = Label() + self._prev_block_closed = False #XXX might be a problem with empty blocks # ---------------------------------------------------------------- # The public Builder interface @@ -183,8 +192,9 @@ log('Builder.end') self.asm.append('}') asm_string = '\n'.join(self.asm) - log(asm_string) + #log(asm_string) llvmjit.parse(asm_string) + llvmjit.transform(3) #optimize module (should be on functions actually) function = llvmjit.getNamedFunction(self.rgenop.name) entrypoint = llvmjit.getPointerToFunctionAsInt(function) #how to cast a ctypes ptr to int? self.rgenop.gv_entrypoint.value = entrypoint @@ -214,8 +224,8 @@ def _rgenop2_generic(self, llvm_opcode, gv_arg1, gv_arg2): log('Builder._rgenop2_generic: ' + llvm_opcode) gv_result = Var() - self.asm.append(" %s=%s %s,%s" % ( - gv_result.name, llvm_opcode, gv_arg1.operand(), gv_arg2.operand2())) + self.asm.append(' %s=%s %s,%s' % ( + gv_result.operand2(), llvm_opcode, gv_arg1.operand(), gv_arg2.operand2())) return gv_result #def op_int_neg(self, gv_x): @@ -227,7 +237,14 @@ #def op_cast_bool_to_int(self, gv_x): def enter_next_block(self, kinds, args_gv): - log('Builder.enter_next_block TODO') + self.label = Label() + log('Builder.enter_next_block %s' % self.label.operand2()) + if not self._prev_block_closed: #there are not always explicit branches to blocks + self.asm.append(' br ' + self.label.operand()) + self.asm.append(self.label.operand2()) + self.asm.append(' ;phi %s,%s' % (kinds, [a.operand() for a in args_gv])) + self._prev_block_closed = False #easiest, but might be a problem with empty blocks + return self.label #arg_positions = [] #seen = {} #for i in range(len(args_gv)): @@ -241,8 +258,33 @@ # seen[gv.stackpos] = None #return Label(self.mc.tell(), arg_positions, self.stackdepth) + def jump_if_true(self, gv_condition): + log('Builder.jump_if_true') + targetbuilder = self.rgenop.openbuilder() #self._fork() + #XXX will need to keep type (bool/int/float/...) of Vars + no_branch = Label() + self.asm.append(' br bool %s,%s,%s' % ( + gv_condition.operand2(), targetbuilder.label.operand(), no_branch.operand())) + self.asm.append(no_branch.operand2()) + #self.mc.CMP(gv_condition.operand(self), imm8(0)) + #self.mc.JNE(rel32(targetbuilder.mc.tell())) + self._prev_block_closed = True + return targetbuilder + + def op_int_is_true(self, gv_x): + log('Build.op_int_is_true ' + gv_x.operand()) + self.asm.append( ' ;op_int_is_true ' + gv_x.operand()) + return gv_x + + def genop_call(self, sigtoken, gv_fnptr, args_gv): + log('Builder.genop_call') + gv_returnvar = Var() + self.asm.append(' ;genop_call %s,%s,%s' % ( + sigtoken, gv_fnptr, [a.operand() for a in args_gv])) + return gv_returnvar + def finish_and_return(self, sigtoken, gv_returnvar): - log('Builder.finish_and_return') + log('Builder.finish_and_return %s,%s' % (sigtoken, gv_returnvar.operand())) self.asm.append(' ret ' + gv_returnvar.operand()) #numargs = sigtoken # for now #initialstackdepth = numargs + 1 @@ -250,18 +292,23 @@ #self.mc.ADD(esp, imm(WORD * (self.stackdepth - initialstackdepth))) #self.mc.RET() #self._close() + self._prev_block_closed = True def finish_and_goto(self, outputargs_gv, target): - log('Builder.finish_and_goto TODO') + log('Builder.finish_and_goto %s,%s' % ([a.operand() for a in outputargs_gv], target)) + self.asm.append(' ;finish_and_goto %s,%s' % ([a.operand() for a in outputargs_gv], target)) #remap_stack_layout(self, outputargs_gv, target) #self.mc.JMP(rel32(target.startaddr)) #self._close() + self._prev_block_closed = True def flexswitch(self, gv_exitswitch): - log('Builder.flexswitch TODO') + log('Builder.flexswitch ' + gv_exitswitch.operand()) + self.asm.append(' ;flexswitch ' + gv_exitswitch.operand()) result = FlexSwitch(self.rgenop) result.initialize(self, gv_exitswitch) #self._close() + self._prev_block_closed = True return result def show_incremental_progress(self): Modified: pypy/dist/pypy/jit/codegen/llvm/test/test_rgenop.py ============================================================================== --- pypy/dist/pypy/jit/codegen/llvm/test/test_rgenop.py (original) +++ pypy/dist/pypy/jit/codegen/llvm/test/test_rgenop.py Thu Dec 7 11:58:29 2006 @@ -11,7 +11,7 @@ if platform == 'darwin': py.test.skip('Compilation for Darwin not fully support yet (static/dyn lib issue') - super(TestRLLVMGenop, self).compile(runner.argtypes) + return super(TestRLLVMGenop, self).compile(runner, argtypes) def test_branching_direct(self): py.test.skip('WIP') From ericvrp at codespeak.net Thu Dec 7 12:10:25 2006 From: ericvrp at codespeak.net (ericvrp at codespeak.net) Date: Thu, 7 Dec 2006 12:10:25 +0100 (CET) Subject: [pypy-svn] r35422 - pypy/dist/pypy/jit/codegen/llvm Message-ID: <20061207111025.3636A10091@code0.codespeak.net> Author: ericvrp Date: Thu Dec 7 12:10:24 2006 New Revision: 35422 Modified: pypy/dist/pypy/jit/codegen/llvm/rgenop.py Log: add reprs Modified: pypy/dist/pypy/jit/codegen/llvm/rgenop.py ============================================================================== --- pypy/dist/pypy/jit/codegen/llvm/rgenop.py (original) +++ pypy/dist/pypy/jit/codegen/llvm/rgenop.py Thu Dec 7 12:10:24 2006 @@ -25,7 +25,7 @@ def operand2(self): return self.name - #repr? + __repr__ = operand class IntConst(GenConst): @@ -48,7 +48,7 @@ else: return lltype.cast_primitive(T, self.value) - #repr? + __repr__ = operand class AddrConst(GenConst): @@ -73,7 +73,7 @@ else: assert 0, "XXX not implemented" - #repr? + __repr__ = operand n_labels = [0] @@ -90,6 +90,8 @@ def operand2(self): return 'L%d:' % self.label + __repr__ = operand + class FlexSwitch(CodeGenSwitch): @@ -203,7 +205,7 @@ numargs = sigtoken # for now inputargs_gv = [Var() for i in range(numargs)] self.asm.append('int %%%s(%s){' % ( - self.rgenop.name, ','.join([v.operand() for v in inputargs_gv]))) + self.rgenop.name, ','.join([str(v) for v in inputargs_gv]))) return inputargs_gv @specialize.arg(1) @@ -225,7 +227,7 @@ log('Builder._rgenop2_generic: ' + llvm_opcode) gv_result = Var() self.asm.append(' %s=%s %s,%s' % ( - gv_result.operand2(), llvm_opcode, gv_arg1.operand(), gv_arg2.operand2())) + gv_result.operand2(), llvm_opcode, gv_arg1, gv_arg2.operand2())) return gv_result #def op_int_neg(self, gv_x): @@ -240,9 +242,9 @@ self.label = Label() log('Builder.enter_next_block %s' % self.label.operand2()) if not self._prev_block_closed: #there are not always explicit branches to blocks - self.asm.append(' br ' + self.label.operand()) + self.asm.append(' br ' + str(self.label)) self.asm.append(self.label.operand2()) - self.asm.append(' ;phi %s,%s' % (kinds, [a.operand() for a in args_gv])) + self.asm.append(' ;phi %s,%s' % (kinds, args_gv)) self._prev_block_closed = False #easiest, but might be a problem with empty blocks return self.label #arg_positions = [] @@ -264,7 +266,7 @@ #XXX will need to keep type (bool/int/float/...) of Vars no_branch = Label() self.asm.append(' br bool %s,%s,%s' % ( - gv_condition.operand2(), targetbuilder.label.operand(), no_branch.operand())) + gv_condition.operand2(), targetbuilder.label, no_branch)) self.asm.append(no_branch.operand2()) #self.mc.CMP(gv_condition.operand(self), imm8(0)) #self.mc.JNE(rel32(targetbuilder.mc.tell())) @@ -272,20 +274,19 @@ return targetbuilder def op_int_is_true(self, gv_x): - log('Build.op_int_is_true ' + gv_x.operand()) - self.asm.append( ' ;op_int_is_true ' + gv_x.operand()) + log('Build.op_int_is_true ' + str(gv_x)) + self.asm.append( ' ;op_int_is_true ' + str(gv_x)) return gv_x def genop_call(self, sigtoken, gv_fnptr, args_gv): log('Builder.genop_call') gv_returnvar = Var() - self.asm.append(' ;genop_call %s,%s,%s' % ( - sigtoken, gv_fnptr, [a.operand() for a in args_gv])) + self.asm.append(' ;genop_call %s,%s,%s' % (sigtoken, gv_fnptr, args_gv)) return gv_returnvar def finish_and_return(self, sigtoken, gv_returnvar): - log('Builder.finish_and_return %s,%s' % (sigtoken, gv_returnvar.operand())) - self.asm.append(' ret ' + gv_returnvar.operand()) + log('Builder.finish_and_return %s,%s' % (sigtoken, gv_returnvar)) + self.asm.append(' ret ' + str(gv_returnvar)) #numargs = sigtoken # for now #initialstackdepth = numargs + 1 #self.mc.MOV(eax, gv_returnvar.operand(self)) @@ -295,16 +296,16 @@ self._prev_block_closed = True def finish_and_goto(self, outputargs_gv, target): - log('Builder.finish_and_goto %s,%s' % ([a.operand() for a in outputargs_gv], target)) - self.asm.append(' ;finish_and_goto %s,%s' % ([a.operand() for a in outputargs_gv], target)) + log('Builder.finish_and_goto %s,%s' % (outputargs_gv, target)) + self.asm.append(' ;finish_and_goto %s,%s' % (outputargs_gv, target)) #remap_stack_layout(self, outputargs_gv, target) #self.mc.JMP(rel32(target.startaddr)) #self._close() self._prev_block_closed = True def flexswitch(self, gv_exitswitch): - log('Builder.flexswitch ' + gv_exitswitch.operand()) - self.asm.append(' ;flexswitch ' + gv_exitswitch.operand()) + log('Builder.flexswitch ' + str(gv_exitswitch)) + self.asm.append(' ;flexswitch ' + str(gv_exitswitch)) result = FlexSwitch(self.rgenop) result.initialize(self, gv_exitswitch) #self._close() From afayolle at codespeak.net Thu Dec 7 12:16:26 2006 From: afayolle at codespeak.net (afayolle at codespeak.net) Date: Thu, 7 Dec 2006 12:16:26 +0100 (CET) Subject: [pypy-svn] r35423 - pypy/dist/pypy/tool/build Message-ID: <20061207111626.F379710094@code0.codespeak.net> Author: afayolle Date: Thu Dec 7 12:16:24 2006 New Revision: 35423 Modified: pypy/dist/pypy/tool/build/client.py Log: add pypy-c in the zip Modified: pypy/dist/pypy/tool/build/client.py ============================================================================== --- pypy/dist/pypy/tool/build/client.py (original) +++ pypy/dist/pypy/tool/build/client.py Thu Dec 7 12:16:24 2006 @@ -93,6 +93,7 @@ # channelwrapper = ChannelWrapper(channel) buf = StringIO() zip = ZipFile(buf, 'w') + zip.writestr('pypy-c', open('pypy-c').read()) for fpath in res_dir.visit(): try: zip.writestr(fpath.relto(res_dir), fpath.read()) From ericvrp at codespeak.net Thu Dec 7 13:14:24 2006 From: ericvrp at codespeak.net (ericvrp at codespeak.net) Date: Thu, 7 Dec 2006 13:14:24 +0100 (CET) Subject: [pypy-svn] r35429 - pypy/dist/pypy/jit/codegen/llvm Message-ID: <20061207121424.2FFF91008D@code0.codespeak.net> Author: ericvrp Date: Thu Dec 7 13:14:22 2006 New Revision: 35429 Modified: pypy/dist/pypy/jit/codegen/llvm/rgenop.py Log: llvmjit rgenop.. * some fixes for blocks that are still open before a label * more/better debug output * opcode fixes (cast->trunc and div->sdiv) * added op_int_is_true Modified: pypy/dist/pypy/jit/codegen/llvm/rgenop.py ============================================================================== --- pypy/dist/pypy/jit/codegen/llvm/rgenop.py (original) +++ pypy/dist/pypy/jit/codegen/llvm/rgenop.py Thu Dec 7 13:14:22 2006 @@ -175,7 +175,7 @@ class Builder(object): #changed baseclass from (GenBuilder) for better error messages _genop2_generics = { - 'int_add' : 'add' , 'int_sub' : 'sub' , 'int_mul' : 'mul' , 'int_floordiv' : 'div' , + 'int_add' : 'add' , 'int_sub' : 'sub' , 'int_mul' : 'mul' , 'int_floordiv' : 'sdiv' , 'int_mod' : 'rem' , 'int_and' : 'and' , 'int_or' : 'or' , 'int_xor' : 'xor' , 'int_lt' : 'setlt', 'int_le' : 'setle', 'int_eq' : 'seteq', 'int_ne' : 'setne', 'int_gt' : 'setgt', 'int_ge' : 'setge' @@ -191,7 +191,7 @@ # The public Builder interface def end(self): - log('Builder.end') + log('Builder.end ' + self.label.operand2()) self.asm.append('}') asm_string = '\n'.join(self.asm) #log(asm_string) @@ -206,17 +206,30 @@ inputargs_gv = [Var() for i in range(numargs)] self.asm.append('int %%%s(%s){' % ( self.rgenop.name, ','.join([str(v) for v in inputargs_gv]))) + self.asm.append(Label().operand2()) return inputargs_gv + def _close(self): + #XXX should builder take the 'asm' list as a parameter (same function as 'mc' in ri386)? + log('Builder._close') + self._prev_block_closed = True + #self.mc.done() + #self.rgenop.close_mc(self.mc) + #self.mc = None + + def _fork(self): + log('Builder._fork') + return self.rgenop.openbuilder() + @specialize.arg(1) def genop1(self, opname, gv_arg): - #log('Builder.genop1') + #log('Builder.genop1 ' + self.label.operand2()) genmethod = getattr(self, 'op_' + opname) return genmethod(gv_arg) @specialize.arg(1) def genop2(self, opname, gv_arg1, gv_arg2): - #log('Builder.genop2') + #log('Builder.genop2 ' + self.label.operand2()) if opname in self._genop2_generics: return self._rgenop2_generic(self._genop2_generics[opname], gv_arg1, gv_arg2) else: @@ -224,7 +237,7 @@ return genmethod(gv_arg1, gv_arg2) def _rgenop2_generic(self, llvm_opcode, gv_arg1, gv_arg2): - log('Builder._rgenop2_generic: ' + llvm_opcode) + log('Builder._rgenop2_generic %s,%s' % (self.label.operand2(), llvm_opcode)) gv_result = Var() self.asm.append(' %s=%s %s,%s' % ( gv_result.operand2(), llvm_opcode, gv_arg1, gv_arg2.operand2())) @@ -260,60 +273,70 @@ # seen[gv.stackpos] = None #return Label(self.mc.tell(), arg_positions, self.stackdepth) + def jump_if_false(self, gv_condition): + log('Builder.jump_if_false%s,%s' % (self.label.operand2(), gv_condition)) + targetbuilder = self._fork() + no_branch = Label() + #XXX will need to keep type of Vars to get rid of the hardcoded 'bool' in the next line + self.asm.append(' br bool %s,%s,%s' % ( + gv_condition.operand2(), no_branch, targetbuilder.label)) + self.asm.append(no_branch.operand2()) + #self.mc.CMP(gv_condition.operand(self), imm8(0)) + #self.mc.JNE(rel32(targetbuilder.mc.tell())) + return targetbuilder + def jump_if_true(self, gv_condition): - log('Builder.jump_if_true') - targetbuilder = self.rgenop.openbuilder() #self._fork() - #XXX will need to keep type (bool/int/float/...) of Vars + log('Builder.jump_if_true %s,%s' % (self.label.operand2(), gv_condition)) + targetbuilder = self._fork() no_branch = Label() + #XXX will need to keep type (bool/int/float/...) of Vars self.asm.append(' br bool %s,%s,%s' % ( gv_condition.operand2(), targetbuilder.label, no_branch)) self.asm.append(no_branch.operand2()) #self.mc.CMP(gv_condition.operand(self), imm8(0)) #self.mc.JNE(rel32(targetbuilder.mc.tell())) - self._prev_block_closed = True return targetbuilder def op_int_is_true(self, gv_x): log('Build.op_int_is_true ' + str(gv_x)) self.asm.append( ' ;op_int_is_true ' + str(gv_x)) - return gv_x + gv_result = Var() #XXX need to mark it a 'bool' somehow + self.asm.append(' %s=trunc %s to bool' % (gv_result.operand2(), gv_x)) + return gv_result def genop_call(self, sigtoken, gv_fnptr, args_gv): - log('Builder.genop_call') + log('Builder.genop_call ' + self.label.operand2()) gv_returnvar = Var() self.asm.append(' ;genop_call %s,%s,%s' % (sigtoken, gv_fnptr, args_gv)) return gv_returnvar def finish_and_return(self, sigtoken, gv_returnvar): - log('Builder.finish_and_return %s,%s' % (sigtoken, gv_returnvar)) + log('Builder.finish_and_return %s,%s,%s' % (self.label.operand2(), sigtoken, gv_returnvar)) self.asm.append(' ret ' + str(gv_returnvar)) #numargs = sigtoken # for now #initialstackdepth = numargs + 1 #self.mc.MOV(eax, gv_returnvar.operand(self)) #self.mc.ADD(esp, imm(WORD * (self.stackdepth - initialstackdepth))) #self.mc.RET() - #self._close() - self._prev_block_closed = True + self._close() def finish_and_goto(self, outputargs_gv, target): - log('Builder.finish_and_goto %s,%s' % (outputargs_gv, target)) + log('Builder.finish_and_goto %s,%s,%s' % (self.label.operand2(), outputargs_gv, target)) self.asm.append(' ;finish_and_goto %s,%s' % (outputargs_gv, target)) #remap_stack_layout(self, outputargs_gv, target) #self.mc.JMP(rel32(target.startaddr)) - #self._close() - self._prev_block_closed = True + self._close() def flexswitch(self, gv_exitswitch): - log('Builder.flexswitch ' + str(gv_exitswitch)) + log('Builder.flexswitch %s,%s' % (self.label.operand2(), gv_exitswitch)) self.asm.append(' ;flexswitch ' + str(gv_exitswitch)) result = FlexSwitch(self.rgenop) result.initialize(self, gv_exitswitch) - #self._close() - self._prev_block_closed = True + self._close() return result def show_incremental_progress(self): - log('Builder.show_incremental_progress') + log('Builder.show_incremental_progress %s' % self.label) pass From mwh at codespeak.net Thu Dec 7 13:29:41 2006 From: mwh at codespeak.net (mwh at codespeak.net) Date: Thu, 7 Dec 2006 13:29:41 +0100 (CET) Subject: [pypy-svn] r35430 - in pypy/dist/pypy/rpython: . lltypesystem Message-ID: <20061207122941.98C6310088@code0.codespeak.net> Author: mwh Date: Thu Dec 7 13:29:40 2006 New Revision: 35430 Modified: pypy/dist/pypy/rpython/lltypesystem/rpbc.py pypy/dist/pypy/rpython/rpbc.py Log: increase the size considered for the small func set representation (don't worry, it's not used at all by default). code for comparing such representations to None and is_true. Modified: pypy/dist/pypy/rpython/lltypesystem/rpbc.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/rpbc.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/rpbc.py Thu Dec 7 13:29:40 2006 @@ -28,6 +28,10 @@ return hop.genop('adr_eq', [v1, cnull], resulttype=Bool) elif robj1 == none_frozen_pbc_repr: return hop.inputconst(Bool, True) + elif isinstance(robj1, SmallFunctionSetPBCRepr): + v1 = hop.inputarg(robj1, pos) + return hop.genop('char_eq', [v1, inputconst(Char, '\000')], + resulttype=Bool) else: raise TyperError('rtype_is_None of %r' % (robj1)) @@ -132,7 +136,10 @@ pointer_table = malloc(POINTER_TABLE, len(self.descriptions), immortal=True) for i, desc in enumerate(self.descriptions): - pointer_table[i] = self.pointer_repr.convert_desc(desc) + if desc is not None: + pointer_table[i] = self.pointer_repr.convert_desc(desc) + else: + pointer_table[i] = self.pointer_repr.convert_const(None) self.c_pointer_table = inputconst(Ptr(POINTER_TABLE), pointer_table) def get_s_callable(self): @@ -159,6 +166,14 @@ ## def convert_to_concrete_llfn(self, v, shape, index, llop): ## return v + def rtype_is_true(self, hop): + if not self.s_pbc.can_be_None: + return inputconst(Bool, True) + else: + v1, = hop.inputargs(self) + return hop.genop('char_eq', [v1, inputconst(Char, '\000')], + resulttype=Bool) + def rtype_simple_call(self, hop): v_index = hop.inputarg(self, arg=0) v_ptr = hop.llops.convertvar(v_index, self, self.pointer_repr) Modified: pypy/dist/pypy/rpython/rpbc.py ============================================================================== --- pypy/dist/pypy/rpython/rpbc.py (original) +++ pypy/dist/pypy/rpython/rpbc.py Thu Dec 7 13:29:40 2006 @@ -28,7 +28,7 @@ else: getRepr = rtyper.type_system.rpbc.FunctionsPBCRepr if rtyper.getconfig().translation.withsmallfuncsets and \ - 1 < len(self.descriptions) < 4 and \ + 1 < len(self.descriptions) < 120 and \ hasattr(rtyper.type_system.rpbc, 'SmallFunctionSetPBCRepr'): callfamily = self.descriptions.iterkeys().next().getcallfamily() concretetable, uniquerows = get_concrete_calltable(rtyper, callfamily) From mwh at codespeak.net Thu Dec 7 13:38:55 2006 From: mwh at codespeak.net (mwh at codespeak.net) Date: Thu, 7 Dec 2006 13:38:55 +0100 (CET) Subject: [pypy-svn] r35431 - pypy/dist/pypy/rpython/lltypesystem Message-ID: <20061207123855.A123310094@code0.codespeak.net> Author: mwh Date: Thu Dec 7 13:38:53 2006 New Revision: 35431 Modified: pypy/dist/pypy/rpython/lltypesystem/rpbc.py Log: oops, is_true was 180 degrees wrong, also fix rtype_is_None .. Modified: pypy/dist/pypy/rpython/lltypesystem/rpbc.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/rpbc.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/rpbc.py Thu Dec 7 13:38:53 2006 @@ -29,9 +29,12 @@ elif robj1 == none_frozen_pbc_repr: return hop.inputconst(Bool, True) elif isinstance(robj1, SmallFunctionSetPBCRepr): - v1 = hop.inputarg(robj1, pos) - return hop.genop('char_eq', [v1, inputconst(Char, '\000')], - resulttype=Bool) + if robj1.s_pbc.can_be_None: + v1 = hop.inputarg(robj1, pos) + return hop.genop('char_eq', [v1, inputconst(Char, '\000')], + resulttype=Bool) + else: + return inputconst(Bool, False) else: raise TyperError('rtype_is_None of %r' % (robj1)) @@ -171,7 +174,7 @@ return inputconst(Bool, True) else: v1, = hop.inputargs(self) - return hop.genop('char_eq', [v1, inputconst(Char, '\000')], + return hop.genop('char_ne', [v1, inputconst(Char, '\000')], resulttype=Bool) def rtype_simple_call(self, hop): From arigo at codespeak.net Thu Dec 7 14:01:02 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 7 Dec 2006 14:01:02 +0100 (CET) Subject: [pypy-svn] r35432 - pypy/dist/pypy/rpython/lltypesystem Message-ID: <20061207130102.177AF10092@code0.codespeak.net> Author: arigo Date: Thu Dec 7 14:01:01 2006 New Revision: 35432 Modified: pypy/dist/pypy/rpython/lltypesystem/rpbc.py Log: Some (futile) attempt at avoiding global vars that might keep reprs alive forever. Modified: pypy/dist/pypy/rpython/lltypesystem/rpbc.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/rpbc.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/rpbc.py Thu Dec 7 14:01:01 2006 @@ -133,6 +133,7 @@ self.descriptions = list(s_pbc.descriptions) if self.s_pbc.can_be_None: self.descriptions.insert(0, None) + self._conversion_tables = {} def _setup_repr(self): POINTER_TABLE = Array(self.pointer_repr.lowleveltype) @@ -205,11 +206,9 @@ desc, = r_ptr.s_pbc.descriptions return inputconst(Char, r_set.convert_desc(desc)) -_conversion_tables = {} def conversion_table(r_from, r_to): - key = r_from, r_to - if key in _conversion_tables: - return _conversion_tables[key] + if r_to in r_from._conversion_tables: + return r_from._conversion_tables[r_to] else: t = malloc(Array(Char), len(r_from.descriptions), immortal=True) l = [] @@ -224,7 +223,7 @@ r = None else: r = inputconst(Ptr(Array(Char)), t) - _conversion_tables[key] = r + r_from._conversion_tables[r_to] = r return r class __extend__(pairtype(SmallFunctionSetPBCRepr, SmallFunctionSetPBCRepr)): From antocuni at codespeak.net Thu Dec 7 14:22:35 2006 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Thu, 7 Dec 2006 14:22:35 +0100 (CET) Subject: [pypy-svn] r35433 - pypy/dist/pypy/translator Message-ID: <20061207132235.D2CBE1008D@code0.codespeak.net> Author: antocuni Date: Thu Dec 7 14:22:34 2006 New Revision: 35433 Modified: pypy/dist/pypy/translator/driver.py Log: Copy the executable to the goal/ dir only if exe_name is defined. Modified: pypy/dist/pypy/translator/driver.py ============================================================================== --- pypy/dist/pypy/translator/driver.py (original) +++ pypy/dist/pypy/translator/driver.py Thu Dec 7 14:22:34 2006 @@ -581,7 +581,7 @@ unpatch(*self.old_cli_defs) self.log.info("Compiled %s" % filename) - if self.standalone: + if self.standalone and self.exe_name: self.copy_cli_exe() task_compile_cli = taskdef(task_compile_cli, ['source_cli'], 'Compiling CLI source') From pedronis at codespeak.net Thu Dec 7 15:53:06 2006 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Thu, 7 Dec 2006 15:53:06 +0100 (CET) Subject: [pypy-svn] r35438 - pypy/branch/jit-real-world/pypy/jit Message-ID: <20061207145306.A27E71009B@code0.codespeak.net> Author: pedronis Date: Thu Dec 7 15:53:05 2006 New Revision: 35438 Added: pypy/branch/jit-real-world/pypy/jit/TODO.txt (contents, props changed) Log: givien that the stack of things to do for the JIT tends to grow and contain lots of other parts of PyPy kind of work, write down a current todo list to help not forget things. Added: pypy/branch/jit-real-world/pypy/jit/TODO.txt ============================================================================== --- (empty file) +++ pypy/branch/jit-real-world/pypy/jit/TODO.txt Thu Dec 7 15:53:05 2006 @@ -0,0 +1,37 @@ +- review codegen (e.g. getfield/setfield for size != word) + +- [] (getitem) used inside complex try/except ends up using the bound + checking version: transformation after flowgraphing that marks op + with implicit exceptions only if they are inside a precise + try:except: + +- stability + do something about bytecode_trace such that the jit + branch can be merged + +- global merge point and portal should delegate their cache impl. + to the application (to allow keeping things alive correctly) + +- unify the notion of the portal entry cache with an implicit global + merge point (for the purpose of promotion), conceptually at the + beginning of the portal, but concretely implemented in the portal + entry + + + +Improvements +------------- + +- make frames virtual + +- promotions for "python dispatching" + +- do something correct about bytecode_trace + +- floats + +- improve backends (reg. allocation ...) + +- jit-friendlier interpreter (whatever, as needed) + +- reduce the size of the timeshifted code: no dispatch for no + split/merge functions ... From pedronis at codespeak.net Thu Dec 7 16:15:42 2006 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Thu, 7 Dec 2006 16:15:42 +0100 (CET) Subject: [pypy-svn] r35440 - pypy/branch/jit-real-world/pypy/jit Message-ID: <20061207151542.02DB210090@code0.codespeak.net> Author: pedronis Date: Thu Dec 7 16:15:42 2006 New Revision: 35440 Modified: pypy/branch/jit-real-world/pypy/jit/TODO.txt Log: another todo Modified: pypy/branch/jit-real-world/pypy/jit/TODO.txt ============================================================================== --- pypy/branch/jit-real-world/pypy/jit/TODO.txt (original) +++ pypy/branch/jit-real-world/pypy/jit/TODO.txt Thu Dec 7 16:15:42 2006 @@ -17,6 +17,7 @@ entry +- make backend opts usable on the interp+timeshifted interp graph forest Improvements ------------- From auc at codespeak.net Thu Dec 7 16:46:38 2006 From: auc at codespeak.net (auc at codespeak.net) Date: Thu, 7 Dec 2006 16:46:38 +0100 (CET) Subject: [pypy-svn] r35441 - pypy/dist/pypy/objspace Message-ID: <20061207154638.9D70910075@code0.codespeak.net> Author: auc Date: Thu Dec 7 16:46:35 2006 New Revision: 35441 Modified: pypy/dist/pypy/objspace/logic.py Log: fix type Modified: pypy/dist/pypy/objspace/logic.py ============================================================================== --- pypy/dist/pypy/objspace/logic.py (original) +++ pypy/dist/pypy/objspace/logic.py Thu Dec 7 16:46:35 2006 @@ -122,11 +122,11 @@ assert isinstance(w_obj1, W_Root) assert isinstance(w_obj2, W_Root) if space.is_true(space.is_nb_(w_obj1, w_obj2)): - return space.newbool(0) + return space.newint(0) if space.is_true(space.is_free(w_obj1)): if space.is_true(space.is_free(w_obj2)): if space.is_true(alias_of(space, w_obj1, w_obj2)): - return space.newbool(0) # and just go on ... + return space.newint(0) # and just go on ... return parentfn(wait(space, w_obj1), wait(space, w_obj2)) return cmp From arigo at codespeak.net Thu Dec 7 18:11:42 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 7 Dec 2006 18:11:42 +0100 (CET) Subject: [pypy-svn] r35447 - pypy/dist/pypy/translator/tool Message-ID: <20061207171142.9626410080@code0.codespeak.net> Author: arigo Date: Thu Dec 7 18:11:41 2006 New Revision: 35447 Modified: pypy/dist/pypy/translator/tool/make_dot.py Log: link.exitcase can be e.g. chr(1) - use %r for this case. Modified: pypy/dist/pypy/translator/tool/make_dot.py ============================================================================== --- pypy/dist/pypy/translator/tool/make_dot.py (original) +++ pypy/dist/pypy/translator/tool/make_dot.py Thu Dec 7 18:11:41 2006 @@ -192,7 +192,7 @@ name2 = self.blockname(link.target) label = " ".join(map(repr, link.args)) if link.exitcase is not None: - label = "%s: %s" %(link.exitcase, label) + label = "%r: %s" %(link.exitcase, label) self.emit_edge(name, name2, label, style="dotted", color="red") else: self.emit_edge(name, name2, label, style="solid") From mwh at codespeak.net Thu Dec 7 18:34:54 2006 From: mwh at codespeak.net (mwh at codespeak.net) Date: Thu, 7 Dec 2006 18:34:54 +0100 (CET) Subject: [pypy-svn] r35448 - pypy/dist/pypy/translator/tool Message-ID: <20061207173454.DC81010091@code0.codespeak.net> Author: mwh Date: Thu Dec 7 18:34:53 2006 New Revision: 35448 Modified: pypy/dist/pypy/translator/tool/make_dot.py Log: like r35447 but with more effort Modified: pypy/dist/pypy/translator/tool/make_dot.py ============================================================================== --- pypy/dist/pypy/translator/tool/make_dot.py (original) +++ pypy/dist/pypy/translator/tool/make_dot.py Thu Dec 7 18:34:53 2006 @@ -192,7 +192,7 @@ name2 = self.blockname(link.target) label = " ".join(map(repr, link.args)) if link.exitcase is not None: - label = "%r: %s" %(link.exitcase, label) + label = "%s: %s" %(repr(link.exitcase).replace('\\', '\\\\'), label) self.emit_edge(name, name2, label, style="dotted", color="red") else: self.emit_edge(name, name2, label, style="solid") From mwh at codespeak.net Thu Dec 7 19:39:49 2006 From: mwh at codespeak.net (mwh at codespeak.net) Date: Thu, 7 Dec 2006 19:39:49 +0100 (CET) Subject: [pypy-svn] r35453 - pypy/dist/pypy/rpython/lltypesystem Message-ID: <20061207183949.0EDAE100A5@code0.codespeak.net> Author: mwh Date: Thu Dec 7 19:39:48 2006 New Revision: 35453 Modified: pypy/dist/pypy/rpython/lltypesystem/rpbc.py Log: first attempt to dispatch SmallFuncSetRepr-ed calls differently. gets as far as source generation, at least... Modified: pypy/dist/pypy/rpython/lltypesystem/rpbc.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/rpbc.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/rpbc.py Thu Dec 7 19:39:48 2006 @@ -2,10 +2,11 @@ import sys from pypy.annotation.pairtype import pairtype, pair from pypy.annotation import model as annmodel +from pypy.annotation import description from pypy.objspace.flow.model import Constant, Variable from pypy.rpython.lltypesystem.lltype import \ typeOf, Void, ForwardReference, Struct, Bool, Char, \ - Ptr, malloc, nullptr, Array, Signed + Ptr, malloc, nullptr, Array, Signed, FuncType from pypy.rpython.rmodel import Repr, TyperError, inputconst, inputdesc, HalfConcreteWrapper from pypy.rpython.rpbc import samesig,\ commonbase, allattributenames, adjust_shape, \ @@ -134,6 +135,7 @@ if self.s_pbc.can_be_None: self.descriptions.insert(0, None) self._conversion_tables = {} + self._dispatch_cache = {} def _setup_repr(self): POINTER_TABLE = Array(self.pointer_repr.lowleveltype) @@ -145,6 +147,7 @@ else: pointer_table[i] = self.pointer_repr.convert_const(None) self.c_pointer_table = inputconst(Ptr(POINTER_TABLE), pointer_table) + from pypy.objspace.flow import model def get_s_callable(self): return self.s_pbc @@ -170,6 +173,62 @@ ## def convert_to_concrete_llfn(self, v, shape, index, llop): ## return v + def rtype_simple_call(self, hop): + return self.call('simple_call', hop) + + def rtype_call_args(self, hop): + return self.call('call_args', hop) + + def dispatcher(self, shape, index, argtypes, resulttype): + key = shape, index, tuple(argtypes), resulttype + if key in self._dispatch_cache: + return self._dispatch_cache[key] + from pypy.translator.unsimplify import varoftype + from pypy.objspace.flow.model import FunctionGraph, Link, Block, SpaceOperation + inputargs = [varoftype(t) for t in [Char] + argtypes] + startblock = Block(inputargs) + startblock.exitswitch = inputargs[0] + #startblock.operations.append(SpaceOperation('debug_pdb', [], varoftype(Void))) + graph = FunctionGraph("dispatcher", startblock, varoftype(resulttype)) + row_of_graphs = self.callfamily.calltables[shape][index] + links = [] + for i, desc in enumerate(self.descriptions): + if desc is None: + continue + args_v = [varoftype(t) for t in argtypes] + b = Block(args_v) + llfn = self.rtyper.getcallable(row_of_graphs[desc]) + v_fn = inputconst(typeOf(llfn), llfn) + v_result = varoftype(resulttype) + b.operations.append( + SpaceOperation("direct_call", [v_fn] + args_v, v_result)) + b.closeblock(Link([v_result], graph.returnblock)) + links.append(Link(inputargs[1:], b, chr(i))) + links[-1].llexitcase = chr(i) + startblock.closeblock(*links) + self.rtyper.annotator.translator.graphs.append(graph) + ll_ret = self.rtyper.type_system.getcallable(graph) + #FTYPE = FuncType + c_ret = self._dispatch_cache[key] = inputconst(typeOf(ll_ret), ll_ret) + return c_ret + + def call(self, opname, hop): + bk = self.rtyper.annotator.bookkeeper + args = bk.build_args(opname, hop.args_s[1:]) + s_pbc = hop.args_s[0] # possibly more precise than self.s_pbc + descs = s_pbc.descriptions.keys() + shape, index = description.FunctionDesc.variant_for_call_site(bk, self.callfamily, descs, args) + row_of_graphs = self.callfamily.calltables[shape][index] + anygraph = row_of_graphs.itervalues().next() # pick any witness + vlist = [hop.inputarg(self, arg=0)] + vlist += callparse.callparse(self.rtyper, anygraph, hop, opname) + rresult = callparse.getrresult(self.rtyper, anygraph) + hop.exception_is_here() + v_dispatcher = self.dispatcher(shape, index, [v.concretetype for v in vlist[1:]], rresult.lowleveltype) + v_result = hop.genop('direct_call', [v_dispatcher] + vlist, + resulttype=rresult) + return hop.llops.convertvar(v_result, rresult, hop.r_result) + def rtype_is_true(self, hop): if not self.s_pbc.can_be_None: return inputconst(Bool, True) @@ -178,15 +237,15 @@ return hop.genop('char_ne', [v1, inputconst(Char, '\000')], resulttype=Bool) - def rtype_simple_call(self, hop): - v_index = hop.inputarg(self, arg=0) - v_ptr = hop.llops.convertvar(v_index, self, self.pointer_repr) - hop2 = hop.copy() - hop2.args_r[0] = self.pointer_repr - hop2.args_v[0] = v_ptr - return hop2.dispatch() +## def rtype_simple_call(self, hop): +## v_index = hop.inputarg(self, arg=0) +## v_ptr = hop.llops.convertvar(v_index, self, self.pointer_repr) +## hop2 = hop.copy() +## hop2.args_r[0] = self.pointer_repr +## hop2.args_v[0] = v_ptr +## return hop2.dispatch() - rtype_call_args = rtype_simple_call +## rtype_call_args = rtype_simple_call class __extend__(pairtype(SmallFunctionSetPBCRepr, FunctionsPBCRepr)): def convert_from_to((r_set, r_ptr), v, llops): From mwh at codespeak.net Thu Dec 7 20:26:14 2006 From: mwh at codespeak.net (mwh at codespeak.net) Date: Thu, 7 Dec 2006 20:26:14 +0100 (CET) Subject: [pypy-svn] r35455 - pypy/dist/pypy/rpython/test Message-ID: <20061207192614.D26E01008F@code0.codespeak.net> Author: mwh Date: Thu Dec 7 20:26:12 2006 New Revision: 35455 Modified: pypy/dist/pypy/rpython/test/test_rpbc.py Log: add an extremely by-hand simple test of the withsmallfuncsets stuff. Modified: pypy/dist/pypy/rpython/test/test_rpbc.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_rpbc.py (original) +++ pypy/dist/pypy/rpython/test/test_rpbc.py Thu Dec 7 20:26:12 2006 @@ -1750,5 +1750,32 @@ class TestOOtype(BaseTestRPBC, OORtypeMixin): pass +def test_smallfuncsets_simple(): + from pypy.translator.translator import TranslationContext, graphof + from pypy.config.pypyoption import get_pypy_config + from pypy.rpython.llinterp import LLInterpreter + config = get_pypy_config(translating=True) + config.translation.withsmallfuncsets = True + def g(x): + return x + 1 + def h(x): + return x - 1 + def f(x, y): + if y > 0: + func = g + else: + func = h + return func(x) + t = TranslationContext(config=config) + a = t.buildannotator() + a.build_types(f, [int, int]) + rtyper = t.buildrtyper() + rtyper.specialize() + graph = graphof(t, f) + interp = LLInterpreter(rtyper) + res = interp.eval_graph(graph, [0, 0]) + assert res == -1 + res = interp.eval_graph(graph, [0, 1]) + assert res == 1 From mwh at codespeak.net Thu Dec 7 20:37:05 2006 From: mwh at codespeak.net (mwh at codespeak.net) Date: Thu, 7 Dec 2006 20:37:05 +0100 (CET) Subject: [pypy-svn] r35456 - in pypy/dist/pypy: config rpython rpython/test Message-ID: <20061207193705.2072C1009B@code0.codespeak.net> Author: mwh Date: Thu Dec 7 20:37:01 2006 New Revision: 35456 Modified: pypy/dist/pypy/config/translationoption.py pypy/dist/pypy/rpython/rpbc.py pypy/dist/pypy/rpython/test/test_rpbc.py Log: make withsmallfuncsets an IntOption Modified: pypy/dist/pypy/config/translationoption.py ============================================================================== --- pypy/dist/pypy/config/translationoption.py (original) +++ pypy/dist/pypy/config/translationoption.py Thu Dec 7 20:37:01 2006 @@ -36,8 +36,9 @@ cmdline="-d --debug", default=False), BoolOption("insist", "Try hard to go on RTyping", default=False, cmdline="--insist"), - BoolOption("withsmallfuncsets", "Represent small groups of functions as small integers", - default=False), + IntOption("withsmallfuncsets", + "Represent groups of less funtions than this as indices into an array", + default=0), BoolOption("countmallocs", "Count mallocs and frees", default=False, cmdline=None), Modified: pypy/dist/pypy/rpython/rpbc.py ============================================================================== --- pypy/dist/pypy/rpython/rpbc.py (original) +++ pypy/dist/pypy/rpython/rpbc.py Thu Dec 7 20:37:01 2006 @@ -27,8 +27,7 @@ getRepr = OverriddenFunctionPBCRepr else: getRepr = rtyper.type_system.rpbc.FunctionsPBCRepr - if rtyper.getconfig().translation.withsmallfuncsets and \ - 1 < len(self.descriptions) < 120 and \ + if 1 < len(self.descriptions) < rtyper.getconfig().translation.withsmallfuncsets and \ hasattr(rtyper.type_system.rpbc, 'SmallFunctionSetPBCRepr'): callfamily = self.descriptions.iterkeys().next().getcallfamily() concretetable, uniquerows = get_concrete_calltable(rtyper, callfamily) Modified: pypy/dist/pypy/rpython/test/test_rpbc.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_rpbc.py (original) +++ pypy/dist/pypy/rpython/test/test_rpbc.py Thu Dec 7 20:37:01 2006 @@ -1750,12 +1750,12 @@ class TestOOtype(BaseTestRPBC, OORtypeMixin): pass -def test_smallfuncsets_simple(): +def test_smallfuncsets_basic(): from pypy.translator.translator import TranslationContext, graphof from pypy.config.pypyoption import get_pypy_config from pypy.rpython.llinterp import LLInterpreter config = get_pypy_config(translating=True) - config.translation.withsmallfuncsets = True + config.translation.withsmallfuncsets = 10 def g(x): return x + 1 From ericvrp at codespeak.net Thu Dec 7 22:52:44 2006 From: ericvrp at codespeak.net (ericvrp at codespeak.net) Date: Thu, 7 Dec 2006 22:52:44 +0100 (CET) Subject: [pypy-svn] r35463 - in pypy/dist/pypy/jit/codegen/llvm: . test Message-ID: <20061207215244.7689110080@code0.codespeak.net> Author: ericvrp Date: Thu Dec 7 22:52:42 2006 New Revision: 35463 Modified: pypy/dist/pypy/jit/codegen/llvm/rgenop.py pypy/dist/pypy/jit/codegen/llvm/test/test_rgenop.py Log: llvmjit rgenop.. * added some sort of function name resolution (currently used by the test_rgenop.py test_fact_direct test (skipped)) * a bunch of changed/added debug statements * it seems all blocks of all builders come out and in the expected order now * fixup branches are inserted in the correct places (or so it seems at the moment) to make sure that all blocks end in a terminator instruction * bug: jump_if_true/false does not always know where te jump to. a fix is simple not making me happy, so more thinking is required first. * worries: getting the phi nodes right seems really painfull especially with the hacked in fixup branches. I want to think a little about using alloca's (like llvm-gcc does) because it looks like phi nodes will no longer be needed. On the downside the llvm assembly will look much uglier. The generated code will be of similar quality after optimization transformations. Modified: pypy/dist/pypy/jit/codegen/llvm/rgenop.py ============================================================================== --- pypy/dist/pypy/jit/codegen/llvm/rgenop.py (original) +++ pypy/dist/pypy/jit/codegen/llvm/rgenop.py Thu Dec 7 22:52:42 2006 @@ -81,14 +81,14 @@ class Label(GenLabel): def __init__(self): - self.label = n_labels[0] + self.label = 'L' + str(n_labels[0]) n_labels[0] += 1 def operand(self): - return 'label %%L%d' % self.label + return 'label %' + self.label def operand2(self): - return 'L%d:' % self.label + return self.label + ':' __repr__ = operand @@ -181,24 +181,30 @@ 'int_gt' : 'setgt', 'int_ge' : 'setge' } - def __init__(self, rgenop): - self.rgenop = rgenop - self.asm = [] #list of llvm assembly source code lines + def __init__(self, rgenop, asm, prev_block_closed=False): self.label = Label() - self._prev_block_closed = False #XXX might be a problem with empty blocks + log('%s Builder.__init__' % self.label.operand2()) + self.rgenop = rgenop + self.asm = asm #list of llvm assembly source code lines + self.prev_block_closed = prev_block_closed #XXX might be a problem with empty blocks # ---------------------------------------------------------------- # The public Builder interface def end(self): - log('Builder.end ' + self.label.operand2()) - self.asm.append('}') - asm_string = '\n'.join(self.asm) - #log(asm_string) + log('%s Builder.end' % self.label.operand2()) + self.rgenop.asms.append(['}']) + #log(self.rgenop.asms) + asm_string = '' + for asm in self.rgenop.asms: + asm_string += '\n'.join(asm) + '\n\n' + self.rgenop.asms = None + log(asm_string) llvmjit.parse(asm_string) llvmjit.transform(3) #optimize module (should be on functions actually) function = llvmjit.getNamedFunction(self.rgenop.name) entrypoint = llvmjit.getPointerToFunctionAsInt(function) #how to cast a ctypes ptr to int? + self.rgenop.funcname[entrypoint] = self.rgenop.funcname[self.rgenop.gv_entrypoint.value] self.rgenop.gv_entrypoint.value = entrypoint def _write_prologue(self, sigtoken): @@ -206,30 +212,34 @@ inputargs_gv = [Var() for i in range(numargs)] self.asm.append('int %%%s(%s){' % ( self.rgenop.name, ','.join([str(v) for v in inputargs_gv]))) - self.asm.append(Label().operand2()) + self.asm.append(self.label.operand2()) return inputargs_gv def _close(self): - #XXX should builder take the 'asm' list as a parameter (same function as 'mc' in ri386)? - log('Builder._close') - self._prev_block_closed = True + log('%s Builder._close' % self.label.operand2()) + #self.rgenop.close_asm(self.asm) + self.asm = None + self.prev_block_closed = True #self.mc.done() #self.rgenop.close_mc(self.mc) #self.mc = None def _fork(self): - log('Builder._fork') - return self.rgenop.openbuilder() + log('%s Builder._fork' % self.label.operand2()) + self.prev_block_closed = True + targetbuilder = self.rgenop.openbuilder(False) + targetbuilder.asm.append(targetbuilder.label.operand2()) #another HACK + return targetbuilder @specialize.arg(1) def genop1(self, opname, gv_arg): - #log('Builder.genop1 ' + self.label.operand2()) + #log('%s Builder.genop1' % self.label.operand2()) genmethod = getattr(self, 'op_' + opname) return genmethod(gv_arg) @specialize.arg(1) def genop2(self, opname, gv_arg1, gv_arg2): - #log('Builder.genop2 ' + self.label.operand2()) + #log('%s Builder.genop2' % self.label.operand2()) if opname in self._genop2_generics: return self._rgenop2_generic(self._genop2_generics[opname], gv_arg1, gv_arg2) else: @@ -237,7 +247,8 @@ return genmethod(gv_arg1, gv_arg2) def _rgenop2_generic(self, llvm_opcode, gv_arg1, gv_arg2): - log('Builder._rgenop2_generic %s,%s' % (self.label.operand2(), llvm_opcode)) + log('%s Builder._rgenop2_generic %s %s,%s' % ( + self.label.operand2(), llvm_opcode, gv_arg1, gv_arg2.operand2())) gv_result = Var() self.asm.append(' %s=%s %s,%s' % ( gv_result.operand2(), llvm_opcode, gv_arg1, gv_arg2.operand2())) @@ -252,13 +263,17 @@ #def op_cast_bool_to_int(self, gv_x): def enter_next_block(self, kinds, args_gv): - self.label = Label() - log('Builder.enter_next_block %s' % self.label.operand2()) - if not self._prev_block_closed: #there are not always explicit branches to blocks - self.asm.append(' br ' + str(self.label)) + label = Label() + log('%s Builder.enter_next_block (was %s), prev_block_closed=%s' % ( + label.operand2(), self.label.operand2(), str(self.prev_block_closed))) + self.label = label + if not self.prev_block_closed: #there are not always explicit branches to blocks + self.asm.append(' br ' + str(self.label) + ' ;fixup') self.asm.append(self.label.operand2()) - self.asm.append(' ;phi %s,%s' % (kinds, args_gv)) - self._prev_block_closed = False #easiest, but might be a problem with empty blocks + #XXX These phi nodes seems to get really messy especially with the 'fixup' branches. + #XXX Perhaps using alloca's and omitting the phi nodes does make some sense. + self.asm.append(' ;phi %s' % args_gv) + self.prev_block_closed = False #easiest, but might be a problem with empty blocks return self.label #arg_positions = [] #seen = {} @@ -274,44 +289,63 @@ #return Label(self.mc.tell(), arg_positions, self.stackdepth) def jump_if_false(self, gv_condition): - log('Builder.jump_if_false%s,%s' % (self.label.operand2(), gv_condition)) + log('%s Builder.jump_if_false %s' % (self.label.operand2(), gv_condition)) targetbuilder = self._fork() - no_branch = Label() + + #XXX the next couple of lines are incorrect! Should we make this a two-pass algorithm? + no_branch = Label() #XXX should be this Builder's next 'enter_next_block' label + global n_labels + n_labels[0] -= 1 #HACK HACK HACK #XXX will need to keep type of Vars to get rid of the hardcoded 'bool' in the next line + targetlabel = targetbuilder.label + self.asm.append(' br bool %s,%s,%s' % ( - gv_condition.operand2(), no_branch, targetbuilder.label)) - self.asm.append(no_branch.operand2()) + gv_condition.operand2(), no_branch, targetlabel)) + #XXX self.asm.append(no_branch.operand2()) #self.mc.CMP(gv_condition.operand(self), imm8(0)) #self.mc.JNE(rel32(targetbuilder.mc.tell())) return targetbuilder def jump_if_true(self, gv_condition): - log('Builder.jump_if_true %s,%s' % (self.label.operand2(), gv_condition)) + log('%s Builder.jump_if_true %s' % (self.label.operand2(), gv_condition)) targetbuilder = self._fork() - no_branch = Label() + + #XXX the next couple of lines are incorrect! Should we make this a two-pass algorithm? + no_branch = Label() #XXX should be this Builder's next 'enter_next_block' label + global n_labels + n_labels[0] -= 1 #HACK HACK HACK #XXX will need to keep type (bool/int/float/...) of Vars + targetlabel = targetbuilder.label + self.asm.append(' br bool %s,%s,%s' % ( - gv_condition.operand2(), targetbuilder.label, no_branch)) - self.asm.append(no_branch.operand2()) + gv_condition.operand2(), targetlabel, no_branch)) + #XXX self.asm.append(no_branch.operand2()) #self.mc.CMP(gv_condition.operand(self), imm8(0)) #self.mc.JNE(rel32(targetbuilder.mc.tell())) return targetbuilder def op_int_is_true(self, gv_x): - log('Build.op_int_is_true ' + str(gv_x)) - self.asm.append( ' ;op_int_is_true ' + str(gv_x)) + log('%s Build.op_int_is_true %s' % (self.label.operand2(), gv_x)) gv_result = Var() #XXX need to mark it a 'bool' somehow self.asm.append(' %s=trunc %s to bool' % (gv_result.operand2(), gv_x)) return gv_result def genop_call(self, sigtoken, gv_fnptr, args_gv): - log('Builder.genop_call ' + self.label.operand2()) + log('%s Builder.genop_call %s,%s,%s' % ( + self.label.operand2(), sigtoken, gv_fnptr, args_gv)) + #log(str(type(gv_fnptr))) + numargs = sigtoken #for now gv_returnvar = Var() - self.asm.append(' ;genop_call %s,%s,%s' % (sigtoken, gv_fnptr, args_gv)) + #XXX we probably need to call an address directly if we can't resolve the funcname + self.asm.append(' %s=call %s(%s)' % ( + gv_returnvar.operand2(), + self.rgenop.funcname[gv_fnptr.value], + ','.join([str(v) for v in args_gv]))) return gv_returnvar def finish_and_return(self, sigtoken, gv_returnvar): - log('Builder.finish_and_return %s,%s,%s' % (self.label.operand2(), sigtoken, gv_returnvar)) + log('%s Builder.finish_and_return %s,%s' % ( + self.label.operand2(), sigtoken, gv_returnvar)) self.asm.append(' ret ' + str(gv_returnvar)) #numargs = sigtoken # for now #initialstackdepth = numargs + 1 @@ -321,14 +355,15 @@ self._close() def finish_and_goto(self, outputargs_gv, target): - log('Builder.finish_and_goto %s,%s,%s' % (self.label.operand2(), outputargs_gv, target)) - self.asm.append(' ;finish_and_goto %s,%s' % (outputargs_gv, target)) + log('%s Builder.finish_and_goto %s,%s' % ( + self.label.operand2(), outputargs_gv, target)) + self.asm.append(' br %s ;%s' % (target, outputargs_gv)) #remap_stack_layout(self, outputargs_gv, target) #self.mc.JMP(rel32(target.startaddr)) self._close() def flexswitch(self, gv_exitswitch): - log('Builder.flexswitch %s,%s' % (self.label.operand2(), gv_exitswitch)) + log('%s Builder.flexswitch %s' % (self.label.operand2(), gv_exitswitch)) self.asm.append(' ;flexswitch ' + str(gv_exitswitch)) result = FlexSwitch(self.rgenop) result.initialize(self, gv_exitswitch) @@ -336,31 +371,41 @@ return result def show_incremental_progress(self): - log('Builder.show_incremental_progress %s' % self.label) + log('%s Builder.show_incremental_progress' % self.label) pass class RLLVMGenOp(object): #changed baseclass from (AbstractRGenOp) for better error messages + funcname = {} #HACK for looking up function names given a pre/post compilation function pointer + def __init__(self): - #self.mcs = [] # machine code blocks where no-one is currently writing - #self.keepalive_gc_refs = [] - pass + self.asms = [] + + def open_asm(self): + asm = [] + self.asms.append(asm) + return asm + + #def close_asm(self, asm): + # self.asms.append(asm) # ---------------------------------------------------------------- # the public RGenOp interface - def openbuilder(self): - #log('RLLVMGenOp.openbuilder') - return Builder(self) + def openbuilder(self, prev_block_closed): + #log('RLLVMGenOp.openbuilder %s' % (str(prev_block_closed)) + return Builder(self, self.open_asm(), prev_block_closed) def newgraph(self, sigtoken, name): - log('RLLVMGenOp.newgraph') + log('RLLVMGenOp.newgraph %s,%s' % (sigtoken, name)) numargs = sigtoken # for now self.name = name - builder = self.openbuilder() + builder = self.openbuilder(False) #enables initial label inputargs_gv = builder._write_prologue(sigtoken) - self.gv_entrypoint = IntConst(0) #note: updated by Builder.end() (i.e after compilation) + n = len(self.funcname) * 2 + 1 #+1 so we recognize these pre compilation 'pointers' + self.funcname[n] = 'int %' + name #XXX 'int' hardcoded currently as in write_prologue() + self.gv_entrypoint = IntConst(n) #note: updated by Builder.end() (i.e after compilation) return builder, self.gv_entrypoint, inputargs_gv @specialize.genconst(1) Modified: pypy/dist/pypy/jit/codegen/llvm/test/test_rgenop.py ============================================================================== --- pypy/dist/pypy/jit/codegen/llvm/test/test_rgenop.py (original) +++ pypy/dist/pypy/jit/codegen/llvm/test/test_rgenop.py Thu Dec 7 22:52:42 2006 @@ -7,12 +7,10 @@ class TestRLLVMGenop(AbstractRGenOpTests): RGenOp = RLLVMGenOp - def compile(self, runner, argtypes): - if platform == 'darwin': + if platform == 'darwin': + def compile(self, runner, argtypes): py.test.skip('Compilation for Darwin not fully support yet (static/dyn lib issue') - return super(TestRLLVMGenop, self).compile(runner, argtypes) - def test_branching_direct(self): py.test.skip('WIP') From arigo at codespeak.net Fri Dec 8 02:33:23 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 8 Dec 2006 02:33:23 +0100 (CET) Subject: [pypy-svn] r35464 - in pypy/branch/jit-real-world/pypy/jit: codegen codegen/i386 codegen/i386/test goal Message-ID: <20061208013323.CF5D610075@code0.codespeak.net> Author: arigo Date: Fri Dec 8 02:33:20 2006 New Revision: 35464 Modified: pypy/branch/jit-real-world/pypy/jit/codegen/graph2rgenop.py pypy/branch/jit-real-world/pypy/jit/codegen/i386/rgenop.py pypy/branch/jit-real-world/pypy/jit/codegen/i386/test/test_operation.py pypy/branch/jit-real-world/pypy/jit/goal/jitstep.py Log: - support for 1- and 2-bytes fields in structures - increase the maximal code buffer size to a usable value for PyPy Modified: pypy/branch/jit-real-world/pypy/jit/codegen/graph2rgenop.py ============================================================================== --- pypy/branch/jit-real-world/pypy/jit/codegen/graph2rgenop.py (original) +++ pypy/branch/jit-real-world/pypy/jit/codegen/graph2rgenop.py Fri Dec 8 02:33:20 2006 @@ -43,6 +43,17 @@ if op.opname == 'malloc': token = rgenop.allocToken(op.args[0].value) gv_result = builder.genop_malloc_fixedsize(token) + elif op.opname == 'getfield': + token = rgenop.fieldToken(op.args[0].concretetype.TO, + op.args[1].value) + gv_result = builder.genop_getfield(token, + var2gv(op.args[0])) + elif op.opname == 'setfield': + token = rgenop.fieldToken(op.args[0].concretetype.TO, + op.args[1].value) + gv_result = builder.genop_setfield(token, + var2gv(op.args[0]), + var2gv(op.args[2])) elif op.opname == 'malloc_varsize': token = rgenop.varsizeAllocToken(op.args[0].value) gv_result = builder.genop_malloc_varsize(token, Modified: pypy/branch/jit-real-world/pypy/jit/codegen/i386/rgenop.py ============================================================================== --- pypy/branch/jit-real-world/pypy/jit/codegen/i386/rgenop.py (original) +++ pypy/branch/jit-real-world/pypy/jit/codegen/i386/rgenop.py Fri Dec 8 02:33:20 2006 @@ -256,18 +256,33 @@ genmethod = getattr(self, 'op_' + opname) return genmethod(gv_arg1, gv_arg2) - def genop_getfield(self, offset, gv_ptr): - # XXX only for int fields + def genop_getfield(self, (offset, fieldsize), gv_ptr): self.mc.MOV(edx, gv_ptr.operand(self)) - return self.returnvar(mem(edx, offset)) + if fieldsize == WORD: + op = mem(edx, offset) + else: + if fieldsize == 1: + op = mem8(edx, offset) + else: + assert fieldsize == 2 + op = mem(edx, offset) + self.mc.MOVZX(eax, op) + op = eax + return self.returnvar(op) - def genop_setfield(self, offset, gv_ptr, gv_value): - # XXX only for ints for now. + def genop_setfield(self, (offset, fieldsize), gv_ptr, gv_value): self.mc.MOV(eax, gv_value.operand(self)) self.mc.MOV(edx, gv_ptr.operand(self)) - self.mc.MOV(mem(edx, offset), eax) + if fieldsize == 1: + self.mc.MOV(mem8(edx, offset), al) + else: + if fieldsize == 2: + self.mc.o16() # followed by the MOV below + else: + assert fieldsize == WORD + self.mc.MOV(mem(edx, offset), eax) - def genop_getsubstruct(self, offset, gv_ptr): + def genop_getsubstruct(self, (offset, fieldsize), gv_ptr): self.mc.MOV(edx, gv_ptr.operand(self)) self.mc.LEA(eax, mem(edx, offset)) return self.returnvar(eax) @@ -813,13 +828,13 @@ def genop2(self, opname, gv_arg1, gv_arg2): return dummy_var - def genop_getfield(self, offset, gv_ptr): + def genop_getfield(self, fieldtoken, gv_ptr): return dummy_var - def genop_setfield(self, offset, gv_ptr, gv_value): + def genop_setfield(self, fieldtoken, gv_ptr, gv_value): return dummy_var - def genop_getsubstruct(self, offset, gv_ptr): + def genop_getsubstruct(self, fieldtoken, gv_ptr): return dummy_var def genop_getarrayitem(self, arraytoken, gv_ptr, gv_index): @@ -874,6 +889,8 @@ class RI386GenOp(AbstractRGenOp): from pypy.jit.codegen.i386.codebuf import MachineCodeBlock + MC_SIZE = 65536 + def __init__(self): self.mcs = [] # machine code blocks where no-one is currently writing self.keepalive_gc_refs = [] @@ -883,7 +900,8 @@ # XXX think about inserting NOPS for alignment return self.mcs.pop() else: - return self.MachineCodeBlock(65536) # XXX supposed infinite for now + # XXX supposed infinite for now + return self.MachineCodeBlock(self.MC_SIZE) def close_mc(self, mc): # an open 'mc' is ready for receiving code... but it's also ready @@ -925,7 +943,12 @@ @staticmethod @specialize.memo() def fieldToken(T, name): - return llmemory.offsetof(T, name) + FIELD = getattr(T, name) + if isinstance(FIELD, lltype.ContainerType): + fieldsize = 0 # not useful for getsubstruct + else: + fieldsize = llmemory.sizeof(FIELD) + return (llmemory.offsetof(T, name), fieldsize) @staticmethod @specialize.memo() Modified: pypy/branch/jit-real-world/pypy/jit/codegen/i386/test/test_operation.py ============================================================================== --- pypy/branch/jit-real-world/pypy/jit/codegen/i386/test/test_operation.py (original) +++ pypy/branch/jit-real-world/pypy/jit/codegen/i386/test/test_operation.py Fri Dec 8 02:33:20 2006 @@ -9,6 +9,11 @@ from pypy.rlib.rarithmetic import r_uint from ctypes import cast, c_void_p, CFUNCTYPE, c_int +def conv(n): + if not isinstance(n, int): + n = convert_offset_to_int(n) + return n + class RGenOpPacked(RI386GenOp): """Like RI386GenOp, but produces concrete offsets in the tokens @@ -19,23 +24,22 @@ @staticmethod @specialize.memo() def fieldToken(T, name): - return convert_offset_to_int(RI386GenOp.fieldToken(T, name)) + return tuple(map(conv, RI386GenOp.fieldToken(T, name))) @staticmethod @specialize.memo() def arrayToken(A): - return tuple(map(convert_offset_to_int, RI386GenOp.arrayToken(A))) + return tuple(map(conv, RI386GenOp.arrayToken(A))) @staticmethod @specialize.memo() def allocToken(T): - return convert_offset_to_int(RI386GenOp.allocToken(T)) + return conv(RI386GenOp.allocToken(T)) @staticmethod @specialize.memo() def varsizeAllocToken(A): - return tuple(map(convert_offset_to_int, - RI386GenOp.varsizeAllocToken(A))) + return tuple(map(conv, RI386GenOp.varsizeAllocToken(A))) class TestBasic: @@ -175,6 +179,28 @@ for i in range(5): assert fp(i) == fn(i) + def test_char_unichar_fields(self): + S = lltype.GcStruct('S', ('a', lltype.Char), + ('b', lltype.Char), + ('c', lltype.UniChar), + ('d', lltype.UniChar), + ('e', lltype.Signed)) + def fn(): + s = lltype.malloc(S) + s.a = 'A' + s.b = 'b' + s.c = unichr(0x5a6b) + s.d = unichr(0x7c8d) + s.e = -1612 + return ((s.a == 'A') + + (s.b == 'b') + + (s.c == unichr(0x5a6b)) + + (s.d == unichr(0x7c8d)) + + (s.e == -1612)) + fp = self.rgen(fn, []) + res = fp() + assert res == 5 + def test_unsigned(self): for fn in [lambda x, y: x + y, lambda x, y: x - y, Modified: pypy/branch/jit-real-world/pypy/jit/goal/jitstep.py ============================================================================== --- pypy/branch/jit-real-world/pypy/jit/goal/jitstep.py (original) +++ pypy/branch/jit-real-world/pypy/jit/goal/jitstep.py Fri Dec 8 02:33:20 2006 @@ -50,6 +50,7 @@ from pypy.jit.timeshifter.hrtyper import HintRTyper #from pypy.jit.codegen.llgraph.rgenop import RGenOp from pypy.jit.codegen.i386.rgenop import RI386GenOp as RGenOp + RGenOp.MC_SIZE = 32 * 1024 * 1024 # 32MB - but supposed infinite! ha = drv.hannotator t = drv.translator From arigo at codespeak.net Fri Dec 8 02:38:19 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 8 Dec 2006 02:38:19 +0100 (CET) Subject: [pypy-svn] r35465 - pypy/dist/pypy/translator/c Message-ID: <20061208013819.CAB2510075@code0.codespeak.net> Author: arigo Date: Fri Dec 8 02:38:18 2006 New Revision: 35465 Modified: pypy/dist/pypy/translator/c/exceptiontransform.py Log: Silence out this message, which is not useful any more. Modified: pypy/dist/pypy/translator/c/exceptiontransform.py ============================================================================== --- pypy/dist/pypy/translator/c/exceptiontransform.py (original) +++ pypy/dist/pypy/translator/c/exceptiontransform.py Fri Dec 8 02:38:18 2006 @@ -220,9 +220,9 @@ if need_exc_matching: assert lastblock.exitswitch == c_last_exception if not self.raise_analyzer.can_raise(lastblock.operations[-1]): - print ("XXX: operation %s cannot raise, but has exception" - " guarding in graph %s" % (lastblock.operations[-1], - graph)) + #print ("operation %s cannot raise, but has exception" + # " guarding in graph %s" % (lastblock.operations[-1], + # graph)) lastblock.exitswitch = None lastblock.exits = [lastblock.exits[0]] lastblock.exits[0].exitcase = None From arigo at codespeak.net Fri Dec 8 02:55:05 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 8 Dec 2006 02:55:05 +0100 (CET) Subject: [pypy-svn] r35466 - pypy/branch/jit-real-world/pypy/jit/codegen/i386 Message-ID: <20061208015505.A611C10076@code0.codespeak.net> Author: arigo Date: Fri Dec 8 02:55:00 2006 New Revision: 35466 Modified: pypy/branch/jit-real-world/pypy/jit/codegen/i386/viewcode.py Log: Bug fix, and link colors: red for the conditional branches, black for the link at the end of the block (a fallthrough or an unconditional jump). Modified: pypy/branch/jit-real-world/pypy/jit/codegen/i386/viewcode.py ============================================================================== --- pypy/branch/jit-real-world/pypy/jit/codegen/i386/viewcode.py (original) +++ pypy/branch/jit-real-world/pypy/jit/codegen/i386/viewcode.py Fri Dec 8 02:55:00 2006 @@ -100,9 +100,10 @@ if not addrs: continue addr = addrs[-1] - yield i, addr + final = '\tjmp' in line + yield i, addr, final if self.fallthrough: - yield len(lines), self.addr + len(self.data) + yield len(lines), self.addr + len(self.data), True class World(object): @@ -132,7 +133,7 @@ self.ranges.append(coderange) # find cross-references between blocks for r in self.ranges: - for lineno, targetaddr in r.findjumps(): + for lineno, targetaddr, _ in r.findjumps(): self.labeltargets[targetaddr] = True # split blocks at labeltargets # XXX slooooow! @@ -147,7 +148,10 @@ self.ranges.append(CodeRange(i, r.data[ofs:])) r.data = r.data[:ofs] r.fallthrough = True - del r.text + try: + del r.text + except AttributeError: + pass break # hack hack hacked @@ -158,8 +162,12 @@ text = '0x%x\n\n%s' % (r.addr, text) g1.emit_node('N_%x' % r.addr, shape="box", label=text, width=str(width*0.125)) - for lineno, targetaddr in r.findjumps(): - g1.emit_edge('N_%x' % r.addr, 'N_%x' % targetaddr) + for lineno, targetaddr, final in r.findjumps(): + if final: + color = "black" + else: + color = "red" + g1.emit_edge('N_%x' % r.addr, 'N_%x' % targetaddr, color=color) g1.display() From hpk at codespeak.net Fri Dec 8 10:20:35 2006 From: hpk at codespeak.net (hpk at codespeak.net) Date: Fri, 8 Dec 2006 10:20:35 +0100 (CET) Subject: [pypy-svn] r35467 - pypy/extradoc/sprintinfo/leysin-winter-2007 Message-ID: <20061208092035.BCCB610077@code0.codespeak.net> Author: hpk Date: Fri Dec 8 10:20:33 2006 New Revision: 35467 Modified: pypy/extradoc/sprintinfo/leysin-winter-2007/announcement.txt Log: focus on describing the leysin sprint intention ("fully public sprint") and don't yet presume much about the last eu-period sprint planned at trillke. Modified: pypy/extradoc/sprintinfo/leysin-winter-2007/announcement.txt ============================================================================== --- pypy/extradoc/sprintinfo/leysin-winter-2007/announcement.txt (original) +++ pypy/extradoc/sprintinfo/leysin-winter-2007/announcement.txt Fri Dec 8 10:20:33 2006 @@ -4,11 +4,11 @@ .. image:: http://www.ermina.ch/002.JPG The next PyPy sprint will be in Leysin, Switzerland, for the fourth -time. This sprint will be the final public sprint of our EU-funded -period, and a kick-off for the final work on the upcoming PyPy 1.0 -release (scheduled for mid-February). +time. This sprint is a fully public sprint and will also be a kick-off +for the final work on the upcoming PyPy 1.0 release (scheduled for +mid-February). -The sprint is the last chance for students looking for a "summer" job +The sprint is the last best chance for students looking for a "summer" job with PyPy this winter! If you have a proposal and would like to work with us in the mountains please send it in before 15th December to "pypy-tb at codespeak.net" and cross-read this page: From mwh at codespeak.net Fri Dec 8 12:36:53 2006 From: mwh at codespeak.net (mwh at codespeak.net) Date: Fri, 8 Dec 2006 12:36:53 +0100 (CET) Subject: [pypy-svn] r35472 - pypy/dist/pypy/translator/goal Message-ID: <20061208113653.ABDA710075@code0.codespeak.net> Author: mwh Date: Fri Dec 8 12:36:53 2006 New Revision: 35472 Added: pypy/dist/pypy/translator/goal/bench-custom.py - copied, changed from r35467, pypy/dist/pypy/translator/goal/bench-unix.py Log: a somewhat hacked up, somewhat cleaned up version of bench-unix.py, designed for testing a bunch of pypy-c's passed on the command line. also rolled up some loops and added a benchmark ("translate.py --text --batch --backendopt --no-compile targetrpystonedalone.py") From mwh at codespeak.net Fri Dec 8 12:48:47 2006 From: mwh at codespeak.net (mwh at codespeak.net) Date: Fri, 8 Dec 2006 12:48:47 +0100 (CET) Subject: [pypy-svn] r35473 - pypy/dist/pypy/translator/goal Message-ID: <20061208114847.A9D8310075@code0.codespeak.net> Author: mwh Date: Fri Dec 8 12:48:47 2006 New Revision: 35473 Modified: pypy/dist/pypy/translator/goal/bench-custom.py Log: compute the slowdown factor correctly in the ASCENDING_GOOD case Modified: pypy/dist/pypy/translator/goal/bench-custom.py ============================================================================== --- pypy/dist/pypy/translator/goal/bench-custom.py (original) +++ pypy/dist/pypy/translator/goal/bench-custom.py Fri Dec 8 12:48:47 2006 @@ -134,7 +134,10 @@ res = benchmark_result.get_best_result(n) if name not in refs: refs[name] = res - print "%6d%s (%6.1fx)"%(res, units, res/refs[name]), + factor = res/refs[name] + if ascgood: + factor = 1/factor + print "%6d%s (%6.1fx)"%(res, units, factor), sys.stdout.flush() print From ericvrp at codespeak.net Fri Dec 8 13:25:34 2006 From: ericvrp at codespeak.net (ericvrp at codespeak.net) Date: Fri, 8 Dec 2006 13:25:34 +0100 (CET) Subject: [pypy-svn] r35474 - in pypy/dist/pypy/jit/codegen/llvm: . lib test Message-ID: <20061208122534.8C87D10070@code0.codespeak.net> Author: ericvrp Date: Fri Dec 8 13:25:31 2006 New Revision: 35474 Modified: pypy/dist/pypy/jit/codegen/llvm/lib/libllvmjit.cpp pypy/dist/pypy/jit/codegen/llvm/llvmjit.py pypy/dist/pypy/jit/codegen/llvm/rgenop.py pypy/dist/pypy/jit/codegen/llvm/test/test_rgenop.py Log: llvmjit rgenop... * 6 rgenop test pass now, including 3 of the test_*_compile variety * note to myself: print statements in rgenop cause the translated tests to hang * remove usage of __repr__ in rgenop, they did not work while translated * using the op_* methods again instead of the lookup table, didn't work when translated * add a postfix to functionnames when we create a newgraph with the same name Modified: pypy/dist/pypy/jit/codegen/llvm/lib/libllvmjit.cpp ============================================================================== --- pypy/dist/pypy/jit/codegen/llvm/lib/libllvmjit.cpp (original) +++ pypy/dist/pypy/jit/codegen/llvm/lib/libllvmjit.cpp Fri Dec 8 13:25:31 2006 @@ -47,7 +47,16 @@ delete gp_execution_engine; //XXX test if this correctly cleans up including generated code gp_module = new Module("llvmjit"); + if (!gp_module) { + std::cerr << "restart() can't allocate the module\n" << std::flush; + return; + } + gp_execution_engine = ExecutionEngine::create(new ExistingModuleProvider(gp_module), false); + if (!gp_execution_engine) { + std::cerr << "restart() can't allocate the execution engine\n" << std::flush; + return; + } //PrintMachineCode = 1; } @@ -55,6 +64,7 @@ int transform(int optLevel) { //optlevel [0123] if (!gp_module) { + std::cerr << "no module available for transform\n" << std::flush; return -1; } @@ -141,6 +151,14 @@ int parse(const char* llsource) { + if (!gp_module) { + restart(); + } + if (!gp_module) { + std::cerr << "no module available for parse\n" << std::flush; + return false; + } + ParseError parse_error; Module* module = ParseAssemblyString(llsource, gp_module, &parse_error); if (!module) { @@ -225,6 +243,11 @@ // Module methods void* getNamedFunction(const char* name) { + if (!gp_module) { + std::cerr << "no module available for getNamedFunction\n" << std::flush; + return NULL; + } + return gp_module->getNamedFunction(name); //note: can be NULL } Modified: pypy/dist/pypy/jit/codegen/llvm/llvmjit.py ============================================================================== --- pypy/dist/pypy/jit/codegen/llvm/llvmjit.py (original) +++ pypy/dist/pypy/jit/codegen/llvm/llvmjit.py Fri Dec 8 13:25:31 2006 @@ -44,7 +44,7 @@ libraries = (os.path.join(os.path.dirname(path), 'llvmjit'),) llvmjit._FuncPtr = _FuncPtr -#ensure stable state +#ensure stable state (XXX this doesn't seem to get called when translated! We do it in parse!) llvmjit.restart() #exposed functions... Modified: pypy/dist/pypy/jit/codegen/llvm/rgenop.py ============================================================================== --- pypy/dist/pypy/jit/codegen/llvm/rgenop.py (original) +++ pypy/dist/pypy/jit/codegen/llvm/rgenop.py Fri Dec 8 13:25:31 2006 @@ -6,18 +6,22 @@ def log(s): - print str(s) + #print str(s) pass -n_vars = [0] +class Count(object): + n_vars = 0 + n_labels = 0 + +count = Count() + class Var(GenVar): def __init__(self): - global n_vars - self.name = '%v' + str(n_vars[0]) - n_vars[0] += 1 + self.name = '%v' + str(count.n_vars) + count.n_vars += 1 def operand(self): return 'int ' + self.name @@ -25,8 +29,6 @@ def operand2(self): return self.name - __repr__ = operand - class IntConst(GenConst): @@ -48,8 +50,6 @@ else: return lltype.cast_primitive(T, self.value) - __repr__ = operand - class AddrConst(GenConst): @@ -73,16 +73,12 @@ else: assert 0, "XXX not implemented" - __repr__ = operand - - -n_labels = [0] class Label(GenLabel): def __init__(self): - self.label = 'L' + str(n_labels[0]) - n_labels[0] += 1 + self.label = 'L' + str(count.n_labels) + count.n_labels += 1 def operand(self): return 'label %' + self.label @@ -90,8 +86,6 @@ def operand2(self): return self.label + ':' - __repr__ = operand - class FlexSwitch(CodeGenSwitch): @@ -174,13 +168,6 @@ class Builder(object): #changed baseclass from (GenBuilder) for better error messages - _genop2_generics = { - 'int_add' : 'add' , 'int_sub' : 'sub' , 'int_mul' : 'mul' , 'int_floordiv' : 'sdiv' , - 'int_mod' : 'rem' , 'int_and' : 'and' , 'int_or' : 'or' , 'int_xor' : 'xor' , - 'int_lt' : 'setlt', 'int_le' : 'setle', 'int_eq' : 'seteq', 'int_ne' : 'setne', - 'int_gt' : 'setgt', 'int_ge' : 'setge' - } - def __init__(self, rgenop, asm, prev_block_closed=False): self.label = Label() log('%s Builder.__init__' % self.label.operand2()) @@ -211,7 +198,7 @@ numargs = sigtoken # for now inputargs_gv = [Var() for i in range(numargs)] self.asm.append('int %%%s(%s){' % ( - self.rgenop.name, ','.join([str(v) for v in inputargs_gv]))) + self.rgenop.name, ','.join([v.operand() for v in inputargs_gv]))) self.asm.append(self.label.operand2()) return inputargs_gv @@ -240,20 +227,32 @@ @specialize.arg(1) def genop2(self, opname, gv_arg1, gv_arg2): #log('%s Builder.genop2' % self.label.operand2()) - if opname in self._genop2_generics: - return self._rgenop2_generic(self._genop2_generics[opname], gv_arg1, gv_arg2) - else: - genmethod = getattr(self, 'op_' + opname) - return genmethod(gv_arg1, gv_arg2) + genmethod = getattr(self, 'op_' + opname) + return genmethod(gv_arg1, gv_arg2) def _rgenop2_generic(self, llvm_opcode, gv_arg1, gv_arg2): log('%s Builder._rgenop2_generic %s %s,%s' % ( - self.label.operand2(), llvm_opcode, gv_arg1, gv_arg2.operand2())) + self.label.operand2(), llvm_opcode, gv_arg1.operand(), gv_arg2.operand2())) gv_result = Var() self.asm.append(' %s=%s %s,%s' % ( - gv_result.operand2(), llvm_opcode, gv_arg1, gv_arg2.operand2())) + gv_result.operand2(), llvm_opcode, gv_arg1.operand(), gv_arg2.operand2())) return gv_result + def op_int_add(self, gv_x, gv_y): return self._rgenop2_generic('add' , gv_x, gv_y) + def op_int_sub(self, gv_x, gv_y): return self._rgenop2_generic('sub' , gv_x, gv_y) + def op_int_mul(self, gv_x, gv_y): return self._rgenop2_generic('mul' , gv_x, gv_y) + def op_int_floordiv(self, gv_x, gv_y): return self._rgenop2_generic('sdiv' , gv_x, gv_y) + def op_int_mod(self, gv_x, gv_y): return self._rgenop2_generic('rem' , gv_x, gv_y) + def op_int_and(self, gv_x, gv_y): return self._rgenop2_generic('and' , gv_x, gv_y) + def op_int_or(self, gv_x, gv_y): return self._rgenop2_generic('or' , gv_x, gv_y) + def op_int_xor(self, gv_x, gv_y): return self._rgenop2_generic('xor' , gv_x, gv_y) + def op_int_lt(self, gv_x, gv_y): return self._rgenop2_generic('setlt', gv_x, gv_y) + def op_int_le(self, gv_x, gv_y): return self._rgenop2_generic('setle', gv_x, gv_y) + def op_int_eq(self, gv_x, gv_y): return self._rgenop2_generic('seteq', gv_x, gv_y) + def op_int_ne(self, gv_x, gv_y): return self._rgenop2_generic('setne', gv_x, gv_y) + def op_int_gt(self, gv_x, gv_y): return self._rgenop2_generic('setgt', gv_x, gv_y) + def op_int_ge(self, gv_x, gv_y): return self._rgenop2_generic('setge', gv_x, gv_y) + #def op_int_neg(self, gv_x): #def op_int_abs(self, gv_x): #def op_int_invert(self, gv_x): @@ -268,11 +267,11 @@ label.operand2(), self.label.operand2(), str(self.prev_block_closed))) self.label = label if not self.prev_block_closed: #there are not always explicit branches to blocks - self.asm.append(' br ' + str(self.label) + ' ;fixup') + self.asm.append(' br ' + self.label.operand() + ' ;fixup') self.asm.append(self.label.operand2()) #XXX These phi nodes seems to get really messy especially with the 'fixup' branches. #XXX Perhaps using alloca's and omitting the phi nodes does make some sense. - self.asm.append(' ;phi %s' % args_gv) + self.asm.append(' ;phi %s' % [v.operand() for v in args_gv]) self.prev_block_closed = False #easiest, but might be a problem with empty blocks return self.label #arg_positions = [] @@ -289,64 +288,61 @@ #return Label(self.mc.tell(), arg_positions, self.stackdepth) def jump_if_false(self, gv_condition): - log('%s Builder.jump_if_false %s' % (self.label.operand2(), gv_condition)) + log('%s Builder.jump_if_false %s' % (self.label.operand2(), gv_condition.operand())) targetbuilder = self._fork() #XXX the next couple of lines are incorrect! Should we make this a two-pass algorithm? no_branch = Label() #XXX should be this Builder's next 'enter_next_block' label - global n_labels - n_labels[0] -= 1 #HACK HACK HACK + count.n_labels -= 1 #HACK HACK HACK #XXX will need to keep type of Vars to get rid of the hardcoded 'bool' in the next line targetlabel = targetbuilder.label self.asm.append(' br bool %s,%s,%s' % ( - gv_condition.operand2(), no_branch, targetlabel)) + gv_condition.operand2(), no_branch.operand(), targetlabel.operand())) #XXX self.asm.append(no_branch.operand2()) #self.mc.CMP(gv_condition.operand(self), imm8(0)) #self.mc.JNE(rel32(targetbuilder.mc.tell())) return targetbuilder def jump_if_true(self, gv_condition): - log('%s Builder.jump_if_true %s' % (self.label.operand2(), gv_condition)) + log('%s Builder.jump_if_true %s' % (self.label.operand2(), gv_condition.operand())) targetbuilder = self._fork() #XXX the next couple of lines are incorrect! Should we make this a two-pass algorithm? no_branch = Label() #XXX should be this Builder's next 'enter_next_block' label - global n_labels - n_labels[0] -= 1 #HACK HACK HACK + count.n_labels -= 1 #HACK HACK HACK #XXX will need to keep type (bool/int/float/...) of Vars targetlabel = targetbuilder.label self.asm.append(' br bool %s,%s,%s' % ( - gv_condition.operand2(), targetlabel, no_branch)) + gv_condition.operand2(), targetlabel.operand(), no_branch.operand())) #XXX self.asm.append(no_branch.operand2()) #self.mc.CMP(gv_condition.operand(self), imm8(0)) #self.mc.JNE(rel32(targetbuilder.mc.tell())) return targetbuilder def op_int_is_true(self, gv_x): - log('%s Build.op_int_is_true %s' % (self.label.operand2(), gv_x)) + log('%s Build.op_int_is_true %s' % (self.label.operand2(), gv_x.operand())) gv_result = Var() #XXX need to mark it a 'bool' somehow - self.asm.append(' %s=trunc %s to bool' % (gv_result.operand2(), gv_x)) + self.asm.append(' %s=trunc %s to bool' % (gv_result.operand2(), gv_x.operand())) return gv_result def genop_call(self, sigtoken, gv_fnptr, args_gv): log('%s Builder.genop_call %s,%s,%s' % ( - self.label.operand2(), sigtoken, gv_fnptr, args_gv)) - #log(str(type(gv_fnptr))) + self.label.operand2(), sigtoken, gv_fnptr, [v.operand() for v in args_gv])) numargs = sigtoken #for now gv_returnvar = Var() #XXX we probably need to call an address directly if we can't resolve the funcname self.asm.append(' %s=call %s(%s)' % ( gv_returnvar.operand2(), self.rgenop.funcname[gv_fnptr.value], - ','.join([str(v) for v in args_gv]))) + ','.join([v.operand() for v in args_gv]))) return gv_returnvar def finish_and_return(self, sigtoken, gv_returnvar): log('%s Builder.finish_and_return %s,%s' % ( - self.label.operand2(), sigtoken, gv_returnvar)) - self.asm.append(' ret ' + str(gv_returnvar)) + self.label.operand2(), sigtoken, gv_returnvar.operand())) + self.asm.append(' ret ' + gv_returnvar.operand()) #numargs = sigtoken # for now #initialstackdepth = numargs + 1 #self.mc.MOV(eax, gv_returnvar.operand(self)) @@ -355,29 +351,31 @@ self._close() def finish_and_goto(self, outputargs_gv, target): + gv = [v.operand() for v in outputargs_gv] log('%s Builder.finish_and_goto %s,%s' % ( - self.label.operand2(), outputargs_gv, target)) - self.asm.append(' br %s ;%s' % (target, outputargs_gv)) + self.label.operand2(), gv, target.operand())) + self.asm.append(' br %s ;%s' % (target.operand(), gv)) #remap_stack_layout(self, outputargs_gv, target) #self.mc.JMP(rel32(target.startaddr)) self._close() def flexswitch(self, gv_exitswitch): - log('%s Builder.flexswitch %s' % (self.label.operand2(), gv_exitswitch)) - self.asm.append(' ;flexswitch ' + str(gv_exitswitch)) + log('%s Builder.flexswitch %s' % (self.label.operand2(), gv_exitswitch.operand())) + self.asm.append(' ;flexswitch ' + gv_exitswitch.operand()) result = FlexSwitch(self.rgenop) result.initialize(self, gv_exitswitch) self._close() return result def show_incremental_progress(self): - log('%s Builder.show_incremental_progress' % self.label) + log('%s Builder.show_incremental_progress' % self.label.operand()) pass class RLLVMGenOp(object): #changed baseclass from (AbstractRGenOp) for better error messages funcname = {} #HACK for looking up function names given a pre/post compilation function pointer + funcused = {} #we rename functions when encountered multiple times (for test_branching_compile) def __init__(self): self.asms = [] @@ -398,6 +396,12 @@ return Builder(self, self.open_asm(), prev_block_closed) def newgraph(self, sigtoken, name): + if name in self.funcused: + self.funcused[name] += 1 + name = '%s_%d' % (name, self.funcused[name]) + else: + self.funcused[name] = 0 + log('RLLVMGenOp.newgraph %s,%s' % (sigtoken, name)) numargs = sigtoken # for now self.name = name Modified: pypy/dist/pypy/jit/codegen/llvm/test/test_rgenop.py ============================================================================== --- pypy/dist/pypy/jit/codegen/llvm/test/test_rgenop.py (original) +++ pypy/dist/pypy/jit/codegen/llvm/test/test_rgenop.py Fri Dec 8 13:25:31 2006 @@ -11,11 +11,21 @@ def compile(self, runner, argtypes): py.test.skip('Compilation for Darwin not fully support yet (static/dyn lib issue') - def test_branching_direct(self): + def skip(self): py.test.skip('WIP') - test_goto_direct = test_branching_direct - test_if_direct = test_branching_direct - test_switch_direct = test_branching_direct - test_large_switch_direct = test_branching_direct - test_fact_direct = test_branching_direct + test_goto_direct = skip + test_goto_compile = skip + + test_if_direct = skip + test_if_compile = skip + + test_switch_direct = skip + test_switch_compile = skip + + test_large_switch_direct = skip + test_large_switch_compile = skip + + test_fact_direct = skip + test_fact_compile = skip + From antocuni at codespeak.net Fri Dec 8 14:34:39 2006 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Fri, 8 Dec 2006 14:34:39 +0100 (CET) Subject: [pypy-svn] r35479 - pypy/dist/pypy/translator/cli/test Message-ID: <20061208133439.963FE1006F@code0.codespeak.net> Author: antocuni Date: Fri Dec 8 14:34:39 2006 New Revision: 35479 Modified: pypy/dist/pypy/translator/cli/test/test_exception.py Log: gencli testing framework is not able to run these tests, skip them. Modified: pypy/dist/pypy/translator/cli/test/test_exception.py ============================================================================== --- pypy/dist/pypy/translator/cli/test/test_exception.py (original) +++ pypy/dist/pypy/translator/cli/test/test_exception.py Fri Dec 8 14:34:39 2006 @@ -32,3 +32,9 @@ return -1 return x self.interpret_raises(ValueError, fn, [0]) + + def test_raise_and_catch_other(self): + pass + + def test_raise_prebuilt_and_catch_other(self): + pass From arigo at codespeak.net Fri Dec 8 14:51:23 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 8 Dec 2006 14:51:23 +0100 (CET) Subject: [pypy-svn] r35482 - in pypy/branch/jit-real-world/pypy: interpreter jit jit/codegen/i386 module/pypyjit Message-ID: <20061208135123.7C5EF10079@code0.codespeak.net> Author: arigo Date: Fri Dec 8 14:51:20 2006 New Revision: 35482 Modified: pypy/branch/jit-real-world/pypy/interpreter/pyopcode.py pypy/branch/jit-real-world/pypy/jit/TODO.txt pypy/branch/jit-real-world/pypy/jit/codegen/i386/codebuf.py pypy/branch/jit-real-world/pypy/jit/codegen/i386/viewcode.py pypy/branch/jit-real-world/pypy/module/pypyjit/interp_jit.py Log: (pedronis, arigo) A bug fix in our hacked interpreter main loop. More JIT debugging support. Modified: pypy/branch/jit-real-world/pypy/interpreter/pyopcode.py ============================================================================== --- pypy/branch/jit-real-world/pypy/interpreter/pyopcode.py (original) +++ pypy/branch/jit-real-world/pypy/interpreter/pyopcode.py Fri Dec 8 14:51:20 2006 @@ -109,8 +109,8 @@ space = self.space while True: hint(None, global_merge_point=True) + self.last_instr = intmask(next_instr) if not we_are_translated(): # JJJ - self.last_instr = intmask(next_instr) ec.bytecode_trace(self) # For the sequel, force 'next_instr' to be unsigned for performance next_instr = r_uint(self.last_instr) @@ -152,6 +152,7 @@ continue # now inside a 'finally' block if opcode == opcodedesc.YIELD_VALUE.index: + #self.last_instr = intmask(next_instr - 1) XXX clean up! w_yieldvalue = self.valuestack.pop() return w_yieldvalue Modified: pypy/branch/jit-real-world/pypy/jit/TODO.txt ============================================================================== --- pypy/branch/jit-real-world/pypy/jit/TODO.txt (original) +++ pypy/branch/jit-real-world/pypy/jit/TODO.txt Fri Dec 8 14:51:20 2006 @@ -1,4 +1,4 @@ -- review codegen (e.g. getfield/setfield for size != word) +- fix the XXXs in codegen - [] (getitem) used inside complex try/except ends up using the bound checking version: transformation after flowgraphing that marks op @@ -36,3 +36,8 @@ - reduce the size of the timeshifted code: no dispatch for no split/merge functions ... + +- insert hints to forget uninteresting constants, e.g. the + initial 0 of RPython list iterators + +- pyopcode.compare_dispatch_table => switch statement Modified: pypy/branch/jit-real-world/pypy/jit/codegen/i386/codebuf.py ============================================================================== --- pypy/branch/jit-real-world/pypy/jit/codegen/i386/codebuf.py (original) +++ pypy/branch/jit-real-world/pypy/jit/codegen/i386/codebuf.py Fri Dec 8 14:51:20 2006 @@ -61,6 +61,7 @@ class MachineCodeDumper: enabled = True log_fd = -1 + sys_executable = None def open(self): if self.log_fd < 0: @@ -77,6 +78,12 @@ os.write(2, "could not create log file\n") self.enabled = False return False + # log the executable name + from pypy.jit.codegen.hlinfo import highleveljitinfo + os.write(self.log_fd, 'BACKEND i386\n') + if highleveljitinfo.sys_executable: + os.write(self.log_fd, 'SYS_EXECUTABLE %s\n' % ( + highleveljitinfo.sys_executable,)) return True def dump(self, cb, tag, pos, msg): Modified: pypy/branch/jit-real-world/pypy/jit/codegen/i386/viewcode.py ============================================================================== --- pypy/branch/jit-real-world/pypy/jit/codegen/i386/viewcode.py (original) +++ pypy/branch/jit-real-world/pypy/jit/codegen/i386/viewcode.py Fri Dec 8 14:51:20 2006 @@ -20,24 +20,42 @@ # Some support code from Psyco. There is more over there, # I am porting it in a lazy fashion... See py-utils/xam.py -# the disassembler to use. 'objdump' writes GNU-style instructions. -# 'ndisasm' uses Intel syntax. XXX ndisasm output parsing is missing... - -objdump = 'objdump -b binary -m i386 --adjust-vma=%(origin)d -D %(file)s' -#objdump = 'ndisasm -o %(origin)d -u %(file)s' if sys.platform == "win32": XXX # lots more in Psyco def machine_code_dump(data, originaddr): + # the disassembler to use. 'objdump' writes GNU-style instructions. + # 'ndisasm' would use Intel syntax, but you need to fix the output parsing. + objdump = 'objdump -b binary -m i386 --adjust-vma=%(origin)d -D %(file)s' + # f = open(tmpfile, 'wb') f.write(data) f.close() g = os.popen(objdump % {'file': tmpfile, 'origin': originaddr}, 'r') result = g.readlines() g.close() - return result + return result[6:] # drop some objdump cruft + +def load_symbols(filename): + # the program that lists symbols, and the output it gives + symbollister = 'nm %s' + re_symbolentry = re.compile(r'([0-9a-fA-F]+)\s\w\s(.*)') + # + symbols = {} + g = os.popen(symbollister % filename, "r") + for line in g: + match = re_symbolentry.match(line) + if match: + addr = long(match.group(1), 16) + name = match.group(2) + if name.startswith('pypy_g_'): + name = '\xb7' + name[7:] + symbols[addr] = name + g.close() + return symbols -re_addr = re.compile(r'[\s,$]0x([0-9a-fA-F]+)') +re_addr = re.compile(r'[\s,$]0x([0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F]+)') +re_lineaddr = re.compile(r'\s*0?x?([0-9a-fA-F]+)') def lineaddresses(line): result = [] @@ -56,7 +74,8 @@ class CodeRange(object): fallthrough = False - def __init__(self, addr, data): + def __init__(self, world, addr, data): + self.world = world self.addr = addr self.data = data @@ -87,7 +106,23 @@ def disassemble(self): if not hasattr(self, 'text'): lines = machine_code_dump(self.data, self.addr) - self.text = ''.join(lines[6:]) # drop some objdump cruft + # instead of adding symbol names in the dumps we could + # also make the 0xNNNNNNNN addresses be red and show the + # symbol name when the mouse is over them + logentries = self.world.logentries + symbols = self.world.symbols + for i, line in enumerate(lines): + match = re_lineaddr.match(line) + if match: + addr = long(match.group(1), 16) + logentry = logentries.get(addr) + if logentry: + lines[i] = '\n%s\n%s' % (logentry, lines[i]) + for addr in lineaddresses(line): + sym = symbols.get(addr) + if sym: + lines[i] = '%s\t%s\n' % (lines[i].rstrip(), sym) + self.text = ''.join(lines) return self.text def findjumps(self): @@ -112,6 +147,8 @@ self.ranges = [] self.labeltargets = {} self.jumps = {} + self.symbols = {} + self.logentries = {} def parse(self, f): for line in f: @@ -123,7 +160,7 @@ offset = int(pieces[2][1:]) addr = baseaddr + offset data = pieces[3].replace(':', '').decode('hex') - coderange = CodeRange(addr, data) + coderange = CodeRange(self, addr, data) # XXX sloooooooow! for r in self.ranges: if addr < r.addr+len(r.data) and r.addr < addr+len(data): @@ -131,6 +168,17 @@ break else: self.ranges.append(coderange) + elif line.startswith('LOG '): + pieces = line.split(None, 3) + assert pieces[1].startswith('@') + assert pieces[2].startswith('+') + baseaddr = long(pieces[1][1:], 16) & 0xFFFFFFFFL + offset = int(pieces[2][1:]) + addr = baseaddr + offset + self.logentries[addr] = pieces[3] + elif line.startswith('SYS_EXECUTABLE '): + filename = line[len('SYS_EXECUTABLE '):].strip() + self.symbols.update(load_symbols(filename)) # find cross-references between blocks for r in self.ranges: for lineno, targetaddr, _ in r.findjumps(): @@ -145,7 +193,7 @@ if i in t: print i ofs = i - r.addr - self.ranges.append(CodeRange(i, r.data[ofs:])) + self.ranges.append(CodeRange(self, i, r.data[ofs:])) r.data = r.data[:ofs] r.fallthrough = True try: @@ -161,7 +209,7 @@ text, width = tab2columns(r.disassemble()) text = '0x%x\n\n%s' % (r.addr, text) g1.emit_node('N_%x' % r.addr, shape="box", label=text, - width=str(width*0.125)) + width=str(width*0.1125)) for lineno, targetaddr, final in r.findjumps(): if final: color = "black" @@ -175,7 +223,7 @@ lines = text.split('\n') columnwidth = [] for line in lines: - columns = line.split('\t') + columns = line.split('\t')[:-1] while len(columnwidth) < len(columns): columnwidth.append(0) for i, s in enumerate(columns): @@ -183,6 +231,7 @@ if not s.endswith(':'): width += 2 columnwidth[i] = max(columnwidth[i], width) + columnwidth.append(1) result = [] for line in lines: columns = line.split('\t') @@ -190,10 +239,9 @@ for width, s in zip(columnwidth, columns): text.append(s.strip().ljust(width)) result.append(' '.join(text)) - if result: - totalwidth = len(result[0]) - else: - totalwidth = 1 + lengths = [len(line) for line in result] + lengths.append(1) + totalwidth = max(lengths) return '\\l'.join(result), totalwidth # ____________________________________________________________ Modified: pypy/branch/jit-real-world/pypy/module/pypyjit/interp_jit.py ============================================================================== --- pypy/branch/jit-real-world/pypy/module/pypyjit/interp_jit.py (original) +++ pypy/branch/jit-real-world/pypy/module/pypyjit/interp_jit.py Fri Dec 8 14:51:20 2006 @@ -73,5 +73,14 @@ # Public interface def enable(space, w_code, w_enabled=True): + # save the app-level sys.executable in JITInfo, where the machine + # code backend can fish for it - XXX the following import will look + # less obscure once codebuf.py is moved to a general + # processor-independent place + from pypy.jit.codegen.hlinfo import highleveljitinfo + if highleveljitinfo.sys_executable is None: + highleveljitinfo.sys_executable = space.str_w( + space.sys.get('executable')) + code = space.interp_w(PyCode, w_code) code.jit_enable = space.is_true(w_enabled) From antocuni at codespeak.net Fri Dec 8 15:13:33 2006 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Fri, 8 Dec 2006 15:13:33 +0100 (CET) Subject: [pypy-svn] r35485 - pypy/dist/pypy/translator/goal Message-ID: <20061208141333.F2DCC10082@code0.codespeak.net> Author: antocuni Date: Fri Dec 8 15:13:33 2006 New Revision: 35485 Modified: pypy/dist/pypy/translator/goal/bench-unix.py Log: Compute the correct size for pypy-cli. Modified: pypy/dist/pypy/translator/goal/bench-unix.py ============================================================================== --- pypy/dist/pypy/translator/goal/bench-unix.py (original) +++ pypy/dist/pypy/translator/goal/bench-unix.py Fri Dec 8 15:13:33 2006 @@ -143,9 +143,15 @@ benchmark_result.update(p, run_pystone(exe), PYSTONE_ASCENDING_GOOD) stone = benchmark_result.get_best_result(p) - codesize = os.popen('size "%s" | tail -n1 | cut -f1'%(exename,)).read().strip() + if 'pypy-cli' in exename: + codesize = 'N/A' + dirname, _ = os.path.split(exe) + exesize = os.path.getsize(os.path.join(dirname, 'main.exe')) + else: + codesize = os.popen('size "%s" | tail -n1 | cut -f1'%(exename,)).read().strip() + exesize = os.path.getsize(exe) - print fmt % (ctime, os.path.getsize(exe), codesize, exename, exename, rich, rich / ref_rich, stone, ref_stone / stone) + print fmt % (ctime, exesize, codesize, exename, exename, rich, rich / ref_rich, stone, ref_stone / stone) sys.stdout.flush() if __name__ == '__main__': From arigo at codespeak.net Fri Dec 8 16:36:17 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 8 Dec 2006 16:36:17 +0100 (CET) Subject: [pypy-svn] r35489 - pypy/branch/jit-real-world/pypy/jit/codegen Message-ID: <20061208153617.0CF9E10086@code0.codespeak.net> Author: arigo Date: Fri Dec 8 16:36:16 2006 New Revision: 35489 Added: pypy/branch/jit-real-world/pypy/jit/codegen/hlinfo.py (contents, props changed) Log: (pedronis, arigo) oops, should have gone with an earlier check-in Added: pypy/branch/jit-real-world/pypy/jit/codegen/hlinfo.py ============================================================================== --- (empty file) +++ pypy/branch/jit-real-world/pypy/jit/codegen/hlinfo.py Fri Dec 8 16:36:16 2006 @@ -0,0 +1,10 @@ + +class HighLevelJITInfo: + """ + A singleton class for the RPython-level JITed program to push information + that the backend can use or log. + """ + sys_executable = None + + +highleveljitinfo = HighLevelJITInfo() From pedronis at codespeak.net Fri Dec 8 16:39:56 2006 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Fri, 8 Dec 2006 16:39:56 +0100 (CET) Subject: [pypy-svn] r35490 - in pypy/branch/jit-real-world/pypy/jit/timeshifter: . test Message-ID: <20061208153956.A23A01006C@code0.codespeak.net> Author: pedronis Date: Fri Dec 8 16:39:47 2006 New Revision: 35490 Modified: pypy/branch/jit-real-world/pypy/jit/timeshifter/hrtyper.py pypy/branch/jit-real-world/pypy/jit/timeshifter/test/test_portal.py pypy/branch/jit-real-world/pypy/jit/timeshifter/test/test_timeshift.py Log: (arigo, pedronis) detect exceptions around residual calls. A pypy-c with the jit doesn't raise strange UnboundLocalErrors anymore. Modified: pypy/branch/jit-real-world/pypy/jit/timeshifter/hrtyper.py ============================================================================== --- pypy/branch/jit-real-world/pypy/jit/timeshifter/hrtyper.py (original) +++ pypy/branch/jit-real-world/pypy/jit/timeshifter/hrtyper.py Fri Dec 8 16:39:47 2006 @@ -337,6 +337,7 @@ TYPES = [v.concretetype for v in origportalgraph.getargs()] argcolorandtypes = unrolling_iterable(zip(argcolors, TYPES)) + fetch_global_excdata = self.fetch_global_excdata def portalreentry(jitstate, *args): i = 0 @@ -387,11 +388,12 @@ gv_res = curbuilder.genop_call(sigtoken, gv_generated, args_gv) + fetch_global_excdata(jitstate) + if RESTYPE == lltype.Void: retbox = None else: retbox = boxbuilder(reskind, gv_res) - jitstate.returnbox = retbox assert jitstate.next is None return jitstate @@ -1300,10 +1302,16 @@ s_result = self.s_RedBox else: s_result = annmodel.s_None - return hop.llops.genmixlevelhelpercall(rtimeshift.ll_gen_residual_call, + v_res = hop.llops.genmixlevelhelpercall( + rtimeshift.ll_gen_residual_call, [self.s_JITState, s_calldesc, self.s_RedBox], [v_jitstate, c_calldesc, v_funcbox ], s_result) + # XXX do something to do this only if the graph can raise + hop.llops.genmixlevelhelpercall(self.fetch_global_excdata, + [self.s_JITState], [v_jitstate], + annmodel.s_None) + return v_res def translate_op_residual_gray_call(self, hop): self.translate_op_residual_red_call(hop, color='gray') Modified: pypy/branch/jit-real-world/pypy/jit/timeshifter/test/test_portal.py ============================================================================== --- pypy/branch/jit-real-world/pypy/jit/timeshifter/test/test_portal.py (original) +++ pypy/branch/jit-real-world/pypy/jit/timeshifter/test/test_portal.py Fri Dec 8 16:39:47 2006 @@ -353,3 +353,30 @@ res = self.timeshift_from_portal(main, evaluate, [4, 7]) assert res == 11 + def test_simple_recursive_portal_call_with_exc(self): + + def main(code, x): + return evaluate(code, x) + + class Bottom(Exception): + pass + + def evaluate(y, x): + hint(y, concrete=True) + if y <= 0: + raise Bottom + try: + z = 1 + evaluate(y - 1, x) + except Bottom: + z = 1 + x + return z + + res = self.timeshift_from_portal(main, evaluate, [3, 2]) + assert res == 5 + + res = self.timeshift_from_portal(main, evaluate, [3, 5]) + assert res == 8 + + res = self.timeshift_from_portal(main, evaluate, [4, 7]) + assert res == 11 + Modified: pypy/branch/jit-real-world/pypy/jit/timeshifter/test/test_timeshift.py ============================================================================== --- pypy/branch/jit-real-world/pypy/jit/timeshifter/test/test_timeshift.py (original) +++ pypy/branch/jit-real-world/pypy/jit/timeshifter/test/test_timeshift.py Fri Dec 8 16:39:47 2006 @@ -1147,3 +1147,56 @@ res = self.timeshift(f, [4, 5, 0], [], policy=P_NOVIRTUAL) assert res == 20 + + def test_residual_red_call(self): + def g(x): + return x+1 + + def f(x): + return 2*g(x) + + class StopAtGPolicy(HintAnnotatorPolicy): + novirtualcontainer = True + + def look_inside_graph(self, graph): + if graph.name == 'g': + return False + return True + + res = self.timeshift(f, [20], [], policy=StopAtGPolicy()) + assert res == 42 + self.check_insns(int_add=0) + + def test_residual_red_call_with_exc(self): + def h(x): + if x > 0: + return x+1 + else: + raise ValueError + + def g(x): + return 2*h(x) + + def f(x): + try: + return g(x) + except ValueError: + return 7 + + class StopAtHPolicy(HintAnnotatorPolicy): + novirtualcontainer = True + + def look_inside_graph(self, graph): + if graph.name == 'h': + return False + return True + + stop_at_h = StopAtHPolicy() + + res = self.timeshift(f, [20], [], policy=stop_at_h) + assert res == 42 + self.check_insns(int_add=0) + + res = self.timeshift(f, [-20], [], policy=stop_at_h) + assert res == 7 + self.check_insns(int_add=0) From ericvrp at codespeak.net Fri Dec 8 17:47:20 2006 From: ericvrp at codespeak.net (ericvrp at codespeak.net) Date: Fri, 8 Dec 2006 17:47:20 +0100 (CET) Subject: [pypy-svn] r35494 - pypy/dist/pypy/jit/codegen/llvm Message-ID: <20061208164720.90DA01007C@code0.codespeak.net> Author: ericvrp Date: Fri Dec 8 17:47:19 2006 New Revision: 35494 Modified: pypy/dist/pypy/jit/codegen/llvm/rgenop.py Log: intermediate llvmjit checkin (moving to x86 machine for testing) Modified: pypy/dist/pypy/jit/codegen/llvm/rgenop.py ============================================================================== --- pypy/dist/pypy/jit/codegen/llvm/rgenop.py (original) +++ pypy/dist/pypy/jit/codegen/llvm/rgenop.py Fri Dec 8 17:47:19 2006 @@ -3,11 +3,12 @@ from pypy.jit.codegen.model import AbstractRGenOp, GenLabel, GenBuilder from pypy.jit.codegen.model import GenVar, GenConst, CodeGenSwitch from pypy.jit.codegen.llvm import llvmjit +from pypy.rlib.objectmodel import we_are_translated def log(s): - #print str(s) - pass + if not we_are_translated(): + print str(s) class Count(object): @@ -24,11 +25,23 @@ count.n_vars += 1 def operand(self): - return 'int ' + self.name + return self.type() + ' ' + self.name def operand2(self): return self.name + def type(self): + return 'int' + + +class VarAddr(Var): + + def __init__(self, var): + self.name = var.name + '_' + + def type(self): + return super(VarAddr, self).type() + '*' + class IntConst(GenConst): @@ -36,11 +49,14 @@ self.value = value def operand(self): - return 'int ' + str(self.value) + return self.type() + ' ' + str(self.value) def operand2(self): return str(self.value) + def type(self): + return 'int' + @specialize.arg(1) def revealconst(self, T): if isinstance(T, lltype.Ptr): @@ -57,11 +73,14 @@ self.addr = addr def operand(self): - return 'int* ' + str(llmemory.cast_adr_to_int(self.addr)) + return self.type() + ' ' + str(llmemory.cast_adr_to_int(self.addr)) def operand2(self): return str(llmemory.cast_adr_to_int(self.addr)) + def type(self): + return 'int*' + @specialize.arg(1) def revealconst(self, T): if T is llmemory.Address: @@ -81,11 +100,20 @@ count.n_labels += 1 def operand(self): - return 'label %' + self.label + return self.type() + ' %' + self.label def operand2(self): return self.label + ':' + def type(self): + return 'label' + + +class EntryLabel(Label): + + def __init(self): + self.label = 'L_' #Block-label for alloca's. The label is never put in the source! + class FlexSwitch(CodeGenSwitch): @@ -169,7 +197,7 @@ class Builder(object): #changed baseclass from (GenBuilder) for better error messages def __init__(self, rgenop, asm, prev_block_closed=False): - self.label = Label() + self.label = EntryLabel() log('%s Builder.__init__' % self.label.operand2()) self.rgenop = rgenop self.asm = asm #list of llvm assembly source code lines @@ -185,7 +213,7 @@ asm_string = '' for asm in self.rgenop.asms: asm_string += '\n'.join(asm) + '\n\n' - self.rgenop.asms = None + self.rgenop.asms = None #XXX or [] ? log(asm_string) llvmjit.parse(asm_string) llvmjit.transform(3) #optimize module (should be on functions actually) @@ -199,8 +227,18 @@ inputargs_gv = [Var() for i in range(numargs)] self.asm.append('int %%%s(%s){' % ( self.rgenop.name, ','.join([v.operand() for v in inputargs_gv]))) - self.asm.append(self.label.operand2()) - return inputargs_gv + + inputargs_gv_ = [] + for v in inputargs_gv: + v_ = VarAddr(v) + inputargs_gv_.append(v_) + self.asm.append(' %s=alloca %s' % (v_.operand2(), v.type())) + self.asm.append(' store %s,%s %s' % (v.operand(), v_.type(), v_.operand2())) + + #self.asm.append(self.label.operand2()) + #note: alloca's should be appended to self.rgenop.asms[0] + self.asm = self.rgenop.open_asm() #note: previous self.asm already appended to self.asms + return inputargs_gv #XXX make this inputargs_gv_ def _close(self): log('%s Builder._close' % self.label.operand2()) @@ -377,9 +415,6 @@ funcname = {} #HACK for looking up function names given a pre/post compilation function pointer funcused = {} #we rename functions when encountered multiple times (for test_branching_compile) - def __init__(self): - self.asms = [] - def open_asm(self): asm = [] self.asms.append(asm) @@ -403,6 +438,7 @@ self.funcused[name] = 0 log('RLLVMGenOp.newgraph %s,%s' % (sigtoken, name)) + self.asms = [] numargs = sigtoken # for now self.name = name builder = self.openbuilder(False) #enables initial label From ericvrp at codespeak.net Fri Dec 8 17:50:04 2006 From: ericvrp at codespeak.net (ericvrp at codespeak.net) Date: Fri, 8 Dec 2006 17:50:04 +0100 (CET) Subject: [pypy-svn] r35495 - pypy/dist/pypy/jit/codegen/llvm Message-ID: <20061208165004.B9CFF10084@code0.codespeak.net> Author: ericvrp Date: Fri Dec 8 17:50:03 2006 New Revision: 35495 Modified: pypy/dist/pypy/jit/codegen/llvm/rgenop.py Log: minor fix Modified: pypy/dist/pypy/jit/codegen/llvm/rgenop.py ============================================================================== --- pypy/dist/pypy/jit/codegen/llvm/rgenop.py (original) +++ pypy/dist/pypy/jit/codegen/llvm/rgenop.py Fri Dec 8 17:50:03 2006 @@ -40,7 +40,7 @@ self.name = var.name + '_' def type(self): - return super(VarAddr, self).type() + '*' + return 'int*' class IntConst(GenConst): From mwh at codespeak.net Fri Dec 8 18:44:52 2006 From: mwh at codespeak.net (mwh at codespeak.net) Date: Fri, 8 Dec 2006 18:44:52 +0100 (CET) Subject: [pypy-svn] r35501 - pypy/dist/pypy/rpython/test Message-ID: <20061208174452.ECE1B10071@code0.codespeak.net> Author: mwh Date: Fri Dec 8 18:44:50 2006 New Revision: 35501 Modified: pypy/dist/pypy/rpython/test/test_llinterp.py pypy/dist/pypy/rpython/test/test_rpbc.py Log: add a config= parameter to test_llinterp.interpreter and friends. use this to run all the test_rpbc tests with --translation-withsmallfuncsets=10 Modified: pypy/dist/pypy/rpython/test/test_llinterp.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_llinterp.py (original) +++ pypy/dist/pypy/rpython/test/test_llinterp.py Fri Dec 8 18:44:50 2006 @@ -32,8 +32,8 @@ return res def gengraph(func, argtypes=[], viewbefore='auto', policy=None, - type_system="lltype", backendopt=False): - t = TranslationContext() + type_system="lltype", backendopt=False, config=None): + t = TranslationContext(config=config) a = t.buildannotator(policy=policy) timelog("annotating", a.build_types, func, argtypes) if viewbefore == 'auto': @@ -61,7 +61,7 @@ _tcache.clear() def get_interpreter(func, values, view='auto', viewbefore='auto', policy=None, - someobjects=False, type_system="lltype", backendopt=False): + someobjects=False, type_system="lltype", backendopt=False, config=None): key = (func,) + tuple([typeOf(x) for x in values])+ (someobjects, backendopt) try: @@ -78,7 +78,7 @@ t, typer, graph = gengraph(func, [annotation(x) for x in values], viewbefore, policy, type_system=type_system, - backendopt=backendopt) + backendopt=backendopt, config=config) interp = LLInterpreter(typer) _tcache[key] = (t, interp, graph) # keep the cache small @@ -92,10 +92,10 @@ return interp, graph def interpret(func, values, view='auto', viewbefore='auto', policy=None, - someobjects=False, type_system="lltype", backendopt=False): + someobjects=False, type_system="lltype", backendopt=False, config=None): interp, graph = get_interpreter(func, values, view, viewbefore, policy, someobjects, type_system=type_system, - backendopt=backendopt) + backendopt=backendopt, config=config) return interp.eval_graph(graph, values) def interpret_raises(exc, func, values, view='auto', viewbefore='auto', Modified: pypy/dist/pypy/rpython/test/test_rpbc.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_rpbc.py (original) +++ pypy/dist/pypy/rpython/test/test_rpbc.py Fri Dec 8 18:44:50 2006 @@ -1750,6 +1750,16 @@ class TestOOtype(BaseTestRPBC, OORtypeMixin): pass +class TestLLtypeSmallFuncSets(TestLLtype): + def setup_class(cls): + from pypy.config.pypyoption import get_pypy_config + cls.config = get_pypy_config(translating=True) + cls.config.translation.withsmallfuncsets = 10 + + def interpret(self, fn, args, **kwds): + kwds['config'] = self.config + return TestLLtype.interpret(self, fn, args, **kwds) + def test_smallfuncsets_basic(): from pypy.translator.translator import TranslationContext, graphof from pypy.config.pypyoption import get_pypy_config From arigo at codespeak.net Fri Dec 8 19:01:19 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 8 Dec 2006 19:01:19 +0100 (CET) Subject: [pypy-svn] r35503 - pypy/dist/pypy/rpython/test Message-ID: <20061208180119.CD5F11007B@code0.codespeak.net> Author: arigo Date: Fri Dec 8 19:01:17 2006 New Revision: 35503 Modified: pypy/dist/pypy/rpython/test/test_rpbc.py Log: Reorder the classes to be in a sane place. Modified: pypy/dist/pypy/rpython/test/test_rpbc.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_rpbc.py (original) +++ pypy/dist/pypy/rpython/test/test_rpbc.py Fri Dec 8 19:01:17 2006 @@ -1492,6 +1492,14 @@ res = self.interpret(f, [2]) assert res == False + +class TestLLtype(BaseTestRPBC, LLRtypeMixin): + pass + +class TestOOtype(BaseTestRPBC, OORtypeMixin): + pass + +# ____________________________________________________________ # We don't care about the following test_hlinvoke tests working on # ootype. Maybe later. This kind of thing is only used in rdict # anyway, that will probably have a different kind of implementation @@ -1744,11 +1752,7 @@ res = interp.eval_graph(ll_h_graph, [None, c_f, c_a]) assert typeOf(res) == A_repr.lowleveltype -class TestLLtype(BaseTestRPBC, LLRtypeMixin): - pass - -class TestOOtype(BaseTestRPBC, OORtypeMixin): - pass +# ____________________________________________________________ class TestLLtypeSmallFuncSets(TestLLtype): def setup_class(cls): From arigo at codespeak.net Fri Dec 8 19:07:36 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 8 Dec 2006 19:07:36 +0100 (CET) Subject: [pypy-svn] r35504 - pypy/branch/jit-real-world/pypy/interpreter Message-ID: <20061208180736.0D96A10086@code0.codespeak.net> Author: arigo Date: Fri Dec 8 19:07:34 2006 New Revision: 35504 Modified: pypy/branch/jit-real-world/pypy/interpreter/miscutils.py Log: Misc change. Modified: pypy/branch/jit-real-world/pypy/interpreter/miscutils.py ============================================================================== --- pypy/branch/jit-real-world/pypy/interpreter/miscutils.py (original) +++ pypy/branch/jit-real-world/pypy/interpreter/miscutils.py Fri Dec 8 19:07:34 2006 @@ -59,7 +59,7 @@ return len(self.items) def empty(self): - return not self.items + return len(self.items) == 0 class FixedStack(RootStack): From arigo at codespeak.net Fri Dec 8 19:08:53 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 8 Dec 2006 19:08:53 +0100 (CET) Subject: [pypy-svn] r35505 - in pypy/branch/jit-real-world/pypy/jit/codegen/i386: . test Message-ID: <20061208180853.9F92410087@code0.codespeak.net> Author: arigo Date: Fri Dec 8 19:08:51 2006 New Revision: 35505 Modified: pypy/branch/jit-real-world/pypy/jit/codegen/i386/codebuf_posix.py pypy/branch/jit-real-world/pypy/jit/codegen/i386/test/test_auto_encoding.py pypy/branch/jit-real-world/pypy/jit/codegen/i386/viewcode.py Log: (pedronis, arigo) Some changes to ease debugging at the back-end level. We learned soon after, though, that when something goes wrong it's likely to be not in the back-end anyway... Modified: pypy/branch/jit-real-world/pypy/jit/codegen/i386/codebuf_posix.py ============================================================================== --- pypy/branch/jit-real-world/pypy/jit/codegen/i386/codebuf_posix.py (original) +++ pypy/branch/jit-real-world/pypy/jit/codegen/i386/codebuf_posix.py Fri Dec 8 19:08:51 2006 @@ -1,7 +1,7 @@ import pypy.rpython.rctypes.implementation # register rctypes types from pypy.rpython.rctypes.tool import ctypes_platform from pypy.rpython.rctypes.tool.libc import libc -from ctypes import POINTER, c_char, c_int +from ctypes import POINTER, c_char, c_int, cast, c_void_p class CConfig: _includes_ = ("sys/types.h", "sys/mman.h") @@ -34,12 +34,17 @@ munmap_.restype = c_int munmap_.includes = ("sys/mman.h",) +class Hint: + pos = -0x4fff0000 # for reproducible results +hint = Hint() + def alloc(map_size): flags = MAP_PRIVATE | MAP_ANONYMOUS prot = PROT_EXEC | PROT_READ | PROT_WRITE - res = mmap_(PTR(), map_size, prot, flags, -1, 0) + res = mmap_(cast(c_void_p(hint.pos), PTR), map_size, prot, flags, -1, 0) if not res: raise MemoryError + hint.pos += map_size return res free = munmap_ Modified: pypy/branch/jit-real-world/pypy/jit/codegen/i386/test/test_auto_encoding.py ============================================================================== --- pypy/branch/jit-real-world/pypy/jit/codegen/i386/test/test_auto_encoding.py (original) +++ pypy/branch/jit-real-world/pypy/jit/codegen/i386/test/test_auto_encoding.py Fri Dec 8 19:08:51 2006 @@ -61,7 +61,10 @@ return map(i386.imm16, v) def imm32_tests(): - v = [0x80000000,0x7FFFFFFF] + [random.randrange(0,65536)<<16 | random.randrange(0,65536) for i in range(COUNT1)] + v = ([0x80000000, 0x7FFFFFFF, 128, 256, -129, -255] + + [random.randrange(0,65536)<<16 | + random.randrange(0,65536) for i in range(COUNT1)] + + [random.randrange(128, 256) for i in range(COUNT1)]) return map(i386.imm32, filter(lambda x: x<-128 or x>=128, v)) def pick1(memSIB, cache=[]): Modified: pypy/branch/jit-real-world/pypy/jit/codegen/i386/viewcode.py ============================================================================== --- pypy/branch/jit-real-world/pypy/jit/codegen/i386/viewcode.py (original) +++ pypy/branch/jit-real-world/pypy/jit/codegen/i386/viewcode.py Fri Dec 8 19:08:51 2006 @@ -41,6 +41,7 @@ symbollister = 'nm %s' re_symbolentry = re.compile(r'([0-9a-fA-F]+)\s\w\s(.*)') # + print 'loading symbols from %s...' % (filename,) symbols = {} g = os.popen(symbollister % filename, "r") for line in g: @@ -52,6 +53,7 @@ name = '\xb7' + name[7:] symbols[addr] = name g.close() + print '%d symbols found' % (len(symbols),) return symbols re_addr = re.compile(r'[\s,$]0x([0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F]+)') @@ -186,12 +188,12 @@ # split blocks at labeltargets # XXX slooooow! t = self.labeltargets - print t + #print t for r in self.ranges: - print r.addr, r.addr + len(r.data) + #print r.addr, r.addr + len(r.data) for i in range(r.addr + 1, r.addr + len(r.data)): if i in t: - print i + #print i ofs = i - r.addr self.ranges.append(CodeRange(self, i, r.data[ofs:])) r.data = r.data[:ofs] From arigo at codespeak.net Fri Dec 8 19:22:48 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 8 Dec 2006 19:22:48 +0100 (CET) Subject: [pypy-svn] r35506 - in pypy/branch/jit-real-world/pypy/jit/timeshifter: . test Message-ID: <20061208182248.65B3D1008A@code0.codespeak.net> Author: arigo Date: Fri Dec 8 19:22:45 2006 New Revision: 35506 Modified: pypy/branch/jit-real-world/pypy/jit/timeshifter/test/test_timeshift.py pypy/branch/jit-real-world/pypy/jit/timeshifter/transform.py Log: (pedronis, arigo) Fix the case of red calls whose return value is not used. Modified: pypy/branch/jit-real-world/pypy/jit/timeshifter/test/test_timeshift.py ============================================================================== --- pypy/branch/jit-real-world/pypy/jit/timeshifter/test/test_timeshift.py (original) +++ pypy/branch/jit-real-world/pypy/jit/timeshifter/test/test_timeshift.py Fri Dec 8 19:22:45 2006 @@ -1200,3 +1200,13 @@ res = self.timeshift(f, [-20], [], policy=stop_at_h) assert res == 7 self.check_insns(int_add=0) + + def test_red_call_ignored_result(self): + def g(n): + return n * 7 + def f(n, m): + g(n) # ignore the result + return m + + res = self.timeshift(f, [4, 212], [], policy=P_NOVIRTUAL) + assert res == 212 Modified: pypy/branch/jit-real-world/pypy/jit/timeshifter/transform.py ============================================================================== --- pypy/branch/jit-real-world/pypy/jit/timeshifter/transform.py (original) +++ pypy/branch/jit-real-world/pypy/jit/timeshifter/transform.py Fri Dec 8 19:22:45 2006 @@ -547,18 +547,22 @@ if color == 'red': assert not self.hannotator.binding(op.result).is_green() - - try: - index = varsalive.index(op.result) - except ValueError: - uses_retval = False + # the result will be either passed as an extra local 0 + # by the caller, or restored by a restore_local + try: + index = varsalive.index(op.result) + except ValueError: + linkargs.insert(0, op.result) + v_result = copyvar(self.hannotator, op.result) + nextblock.inputargs.insert(0, v_result) + else: + del varsalive[index] + old_v_result = linkargs.pop(index) + linkargs.insert(0, old_v_result) + v_result = nextblock.inputargs.pop(index) + nextblock.inputargs.insert(0, v_result) else: - uses_retval = True # it will be restored by a restore_local - del varsalive[index] - old_v_result = linkargs.pop(index) - linkargs.insert(0, old_v_result) - v_result = nextblock.inputargs.pop(index) - nextblock.inputargs.insert(0, v_result) + assert op.result not in varsalive # XXX gray result used reds, greens = self.sort_by_color(varsalive) @@ -599,7 +603,7 @@ v_res = self.genop(nonconstantblock, 'residual_%s_call' % (color,), [op.args[0]], result_like = op.result) - if uses_retval: + if color == 'red': linkargs[0] = v_res nonconstantblock.closeblock(Link(linkargs, nextblock)) From antocuni at codespeak.net Fri Dec 8 20:45:49 2006 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Fri, 8 Dec 2006 20:45:49 +0100 (CET) Subject: [pypy-svn] r35509 - pypy/dist/pypy/rpython Message-ID: <20061208194549.D169C10071@code0.codespeak.net> Author: antocuni Date: Fri Dec 8 20:45:48 2006 New Revision: 35509 Modified: pypy/dist/pypy/rpython/rexternalobj.py Log: bugfix Modified: pypy/dist/pypy/rpython/rexternalobj.py ============================================================================== --- pypy/dist/pypy/rpython/rexternalobj.py (original) +++ pypy/dist/pypy/rpython/rexternalobj.py Fri Dec 8 20:45:48 2006 @@ -61,8 +61,9 @@ def call_method(self, name, hop): vlist = hop.inputargs(self, *(hop.args_r[1:])) + c_name = hop.inputconst(ootype.Void, name) hop.exception_is_here() - return hop.genop('oosend', [Constant(name)] + vlist, resulttype=hop.r_result) + return hop.genop('oosend', [c_name] + vlist, resulttype=hop.r_result) def rtype_is_true(self, hop): vlist = hop.inputargs(self) From ericvrp at codespeak.net Fri Dec 8 22:24:09 2006 From: ericvrp at codespeak.net (ericvrp at codespeak.net) Date: Fri, 8 Dec 2006 22:24:09 +0100 (CET) Subject: [pypy-svn] r35510 - in pypy/dist/pypy/jit/codegen/llvm: . test Message-ID: <20061208212409.A1BA910070@code0.codespeak.net> Author: ericvrp Date: Fri Dec 8 22:24:06 2006 New Revision: 35510 Modified: pypy/dist/pypy/jit/codegen/llvm/rgenop.py pypy/dist/pypy/jit/codegen/llvm/test/test_rgenop.py Log: llvmjit use alloca's to store local variables to avoid having to deal with phi nodes. Alloca returns a pointer to a stack variable. Its return value is assigned only once (so valid SSA form) but the data it points to can be read and written to many times. Thereby avoiding some difficulties. Not more passing tests this time but at least the remaining failures are valid SSA form now. Modified: pypy/dist/pypy/jit/codegen/llvm/rgenop.py ============================================================================== --- pypy/dist/pypy/jit/codegen/llvm/rgenop.py (original) +++ pypy/dist/pypy/jit/codegen/llvm/rgenop.py Fri Dec 8 22:24:06 2006 @@ -36,8 +36,9 @@ class VarAddr(Var): - def __init__(self, var): - self.name = var.name + '_' + def __init__(self, v, asm): + self.name = '%p' + v.name[2:] + asm.append(' %s=alloca %s' % (self.operand2(), v.type())) #note: sideeffect! def type(self): return 'int*' @@ -212,7 +213,7 @@ #log(self.rgenop.asms) asm_string = '' for asm in self.rgenop.asms: - asm_string += '\n'.join(asm) + '\n\n' + asm_string += '\n'.join(asm) + '\n' self.rgenop.asms = None #XXX or [] ? log(asm_string) llvmjit.parse(asm_string) @@ -230,15 +231,14 @@ inputargs_gv_ = [] for v in inputargs_gv: - v_ = VarAddr(v) - inputargs_gv_.append(v_) - self.asm.append(' %s=alloca %s' % (v_.operand2(), v.type())) + v_ = VarAddr(v, self.asm) self.asm.append(' store %s,%s %s' % (v.operand(), v_.type(), v_.operand2())) + inputargs_gv_.append(v_) #self.asm.append(self.label.operand2()) #note: alloca's should be appended to self.rgenop.asms[0] self.asm = self.rgenop.open_asm() #note: previous self.asm already appended to self.asms - return inputargs_gv #XXX make this inputargs_gv_ + return inputargs_gv_ #XXX make this inputargs_gv_ def _close(self): log('%s Builder._close' % self.label.operand2()) @@ -271,10 +271,42 @@ def _rgenop2_generic(self, llvm_opcode, gv_arg1, gv_arg2): log('%s Builder._rgenop2_generic %s %s,%s' % ( self.label.operand2(), llvm_opcode, gv_arg1.operand(), gv_arg2.operand2())) + + #XXX can't this be shorter? + if gv_arg1.is_const or isinstance(gv_arg1, VarAddr): + gv_arg1_ = gv_arg1 + else: + gv_arg1_ = VarAddr(gv_arg1, self.rgenop.asms[0]) + if isinstance(gv_arg1_, VarAddr): + gv_arg1_tmp = Var() + self.asm.append(' %s=load %s' % (gv_arg1_tmp.operand2(), gv_arg1_.operand())) + else: + gv_arg1_tmp = gv_arg1_ + + if gv_arg2.is_const or isinstance(gv_arg2, VarAddr): + gv_arg2_ = gv_arg2 + else: + gv_arg2_ = VarAddr(gv_arg2, self.rgenop.asms[0]) + if isinstance(gv_arg2_, VarAddr): + gv_arg2_tmp = Var() + self.asm.append(' %s=load %s' % (gv_arg2_tmp.operand2(), gv_arg2_.operand())) + else: + gv_arg2_tmp = gv_arg2_ + gv_result = Var() self.asm.append(' %s=%s %s,%s' % ( - gv_result.operand2(), llvm_opcode, gv_arg1.operand(), gv_arg2.operand2())) - return gv_result + gv_result.operand2(), llvm_opcode, gv_arg1_tmp.operand(), gv_arg2_tmp.operand2())) + + if llvm_opcode[:3] == 'set': #HACK + #XXX We assume there will always be a jump_if_true/false right after an op_int_eq/etc. + # Because we don't yet keep track of non-ints it will be difficult to do the + # right thing in jump_if_true/false. So this is a hack we want to fix later! + return gv_result + + gv_result_ = VarAddr(gv_result, self.rgenop.asms[0]) + self.asm.append(' store %s,%s' % (gv_result.operand(), gv_result_.operand())) + + return gv_result_ def op_int_add(self, gv_x, gv_y): return self._rgenop2_generic('add' , gv_x, gv_y) def op_int_sub(self, gv_x, gv_y): return self._rgenop2_generic('sub' , gv_x, gv_y) @@ -301,8 +333,9 @@ def enter_next_block(self, kinds, args_gv): label = Label() - log('%s Builder.enter_next_block (was %s), prev_block_closed=%s' % ( - label.operand2(), self.label.operand2(), str(self.prev_block_closed))) + log('%s Builder.enter_next_block (was %s), prev_block_closed=%s, %s' % ( + label.operand2(), self.label.operand2(), str(self.prev_block_closed), + [v.operand() for v in args_gv])) self.label = label if not self.prev_block_closed: #there are not always explicit branches to blocks self.asm.append(' br ' + self.label.operand() + ' ;fixup') @@ -359,8 +392,13 @@ #self.mc.JNE(rel32(targetbuilder.mc.tell())) return targetbuilder - def op_int_is_true(self, gv_x): - log('%s Build.op_int_is_true %s' % (self.label.operand2(), gv_x.operand())) + def op_int_is_true(self, gv_x_): + log('%s Build.op_int_is_true %s' % (self.label.operand2(), gv_x_.operand())) + if isinstance(gv_x_, VarAddr): + gv_x = Var() + self.asm.append(' %s=load %s' % (gv_x.operand2(), gv_x_.operand())) + else: + gv_x = gv_x_ gv_result = Var() #XXX need to mark it a 'bool' somehow self.asm.append(' %s=trunc %s to bool' % (gv_result.operand2(), gv_x.operand())) return gv_result @@ -377,9 +415,15 @@ ','.join([v.operand() for v in args_gv]))) return gv_returnvar - def finish_and_return(self, sigtoken, gv_returnvar): + def finish_and_return(self, sigtoken, gv_returnvar_): log('%s Builder.finish_and_return %s,%s' % ( - self.label.operand2(), sigtoken, gv_returnvar.operand())) + self.label.operand2(), sigtoken, gv_returnvar_.operand())) + + if isinstance(gv_returnvar_, VarAddr): + gv_returnvar = Var() + self.asm.append(' %s=load %s' % (gv_returnvar.operand2(), gv_returnvar_.operand())) + else: + gv_returnvar = gv_returnvar_ self.asm.append(' ret ' + gv_returnvar.operand()) #numargs = sigtoken # for now #initialstackdepth = numargs + 1 Modified: pypy/dist/pypy/jit/codegen/llvm/test/test_rgenop.py ============================================================================== --- pypy/dist/pypy/jit/codegen/llvm/test/test_rgenop.py (original) +++ pypy/dist/pypy/jit/codegen/llvm/test/test_rgenop.py Fri Dec 8 22:24:06 2006 @@ -28,4 +28,3 @@ test_fact_direct = skip test_fact_compile = skip - From arigo at codespeak.net Sat Dec 9 00:28:22 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 9 Dec 2006 00:28:22 +0100 (CET) Subject: [pypy-svn] r35511 - in pypy/dist/pypy/translator/c: . src Message-ID: <20061208232822.D542410070@code0.codespeak.net> Author: arigo Date: Sat Dec 9 00:28:20 2006 New Revision: 35511 Modified: pypy/dist/pypy/translator/c/primitive.py pypy/dist/pypy/translator/c/src/g_prerequisite.h Log: (pedronis, arigo) Try to use _Bool with gcc. Modified: pypy/dist/pypy/translator/c/primitive.py ============================================================================== --- pypy/dist/pypy/translator/c/primitive.py (original) +++ pypy/dist/pypy/translator/c/primitive.py Sat Dec 9 00:28:20 2006 @@ -151,7 +151,7 @@ Float: 'double @', Char: 'char @', UniChar: 'unsigned int @', - Bool: 'char @', + Bool: 'bool_t @', Void: 'void @', Address: 'void* @', WeakGcAddress: 'GC_hidden_pointer @', @@ -165,7 +165,7 @@ Float: '-1.0', Char: '((char) -1)', UniChar: '((unsigned) -1)', - Bool: '((char) -1)', + Bool: '0 /* error */', Void: '/* error */', Address: 'NULL', WeakGcAddress: 'HIDE_POINTER(NULL)', Modified: pypy/dist/pypy/translator/c/src/g_prerequisite.h ============================================================================== --- pypy/dist/pypy/translator/c/src/g_prerequisite.h (original) +++ pypy/dist/pypy/translator/c/src/g_prerequisite.h Sat Dec 9 00:28:20 2006 @@ -15,3 +15,10 @@ #endif #include + + +#ifdef __GNUC__ /* other platforms too, probably */ +typedef _Bool bool_t; +#else +typedef unsigned char bool_t; +#endif From arigo at codespeak.net Sat Dec 9 00:51:57 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 9 Dec 2006 00:51:57 +0100 (CET) Subject: [pypy-svn] r35512 - in pypy/branch/jit-real-world/pypy: interpreter module/pypyjit Message-ID: <20061208235157.227FF10082@code0.codespeak.net> Author: arigo Date: Sat Dec 9 00:51:55 2006 New Revision: 35512 Modified: pypy/branch/jit-real-world/pypy/interpreter/pyopcode.py pypy/branch/jit-real-world/pypy/module/pypyjit/interp_jit.py Log: (pedronis, arigo) A hack to disable the bytecode trace only in the jited version of the bytecode main loop. Modified: pypy/branch/jit-real-world/pypy/interpreter/pyopcode.py ============================================================================== --- pypy/branch/jit-real-world/pypy/interpreter/pyopcode.py (original) +++ pypy/branch/jit-real-world/pypy/interpreter/pyopcode.py Sat Dec 9 00:51:55 2006 @@ -37,7 +37,10 @@ w_result = operation(w_1, w_2) f.valuestack.push(w_result) - return func_with_new_name(opimpl, "opcode_impl_for_%s" % operationname) + return func_with_new_name(opimpl, "opcode_impl_for_%s" % operationname) + + +BYTECODE_TRACE_ENABLED = True # see also pypy.module.pypyjit class __extend__(pyframe.PyFrame): @@ -110,7 +113,7 @@ while True: hint(None, global_merge_point=True) self.last_instr = intmask(next_instr) - if not we_are_translated(): # JJJ + if BYTECODE_TRACE_ENABLED: ec.bytecode_trace(self) # For the sequel, force 'next_instr' to be unsigned for performance next_instr = r_uint(self.last_instr) Modified: pypy/branch/jit-real-world/pypy/module/pypyjit/interp_jit.py ============================================================================== --- pypy/branch/jit-real-world/pypy/module/pypyjit/interp_jit.py (original) +++ pypy/branch/jit-real-world/pypy/module/pypyjit/interp_jit.py Sat Dec 9 00:51:55 2006 @@ -7,6 +7,7 @@ pypy/jit/* """ import py +import pypy.interpreter.pyopcode # for side-effects from pypy.interpreter.pycode import PyCode from pypy.interpreter.pyframe import PyFrame from pypy.tool.sourcetools import func_with_new_name @@ -52,8 +53,22 @@ def setup2(): # TEMPORARY: only patches dispatch_bytecode. - PyFrame.dispatch_jit = func_with_new_name( - PyFrame.dispatch_bytecode.im_func, 'dispatch_jit') + # make a copy of dispatch_bytecode in which BYTECODE_TRACE_ENABLED is False + # (hack hack!) + src2 = py.code.Source(PyFrame.dispatch_bytecode) + hdr = src2[0].strip() + assert hdr == 'def dispatch_bytecode(self, co_code, next_instr, ec):' + src2 = src2[1:].deindent() + + src2 = src2.putaround( + "def maker(BYTECODE_TRACE_ENABLED):\n" # no comma here + " def dispatch_jit(self, co_code, next_instr, ec):\n", + "#\n" # for indentation :-( + " return dispatch_jit") + #print src2 + d = {} + exec src2.compile() in super_dispatch.func_globals, d + PyFrame.dispatch_jit = d['maker'](BYTECODE_TRACE_ENABLED=False) class __extend__(PyFrame): From arigo at codespeak.net Sat Dec 9 02:08:35 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 9 Dec 2006 02:08:35 +0100 (CET) Subject: [pypy-svn] r35513 - pypy/branch/temp Message-ID: <20061209010835.D54881007B@code0.codespeak.net> Author: arigo Date: Sat Dec 9 02:08:32 2006 New Revision: 35513 Added: pypy/branch/temp/ - copied from r35512, pypy/dist/ Log: A temporary branch to help merge the real-world-jit branch. From arigo at codespeak.net Sat Dec 9 02:31:06 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 9 Dec 2006 02:31:06 +0100 (CET) Subject: [pypy-svn] r35514 - pypy/branch/temp/pypy/rpython Message-ID: <20061209013106.170FF1007B@code0.codespeak.net> Author: arigo Date: Sat Dec 9 02:31:05 2006 New Revision: 35514 Modified: pypy/branch/temp/pypy/rpython/rtyper.py Log: merging of http://codespeak.net/svn/pypy/branch/jit-real-world/pypy/rpython/rtyper.py revisions 35112 to 35513: ------------------------------------------------------------------------ r35219 | arigo | 2006-12-03 16:00:05 +0100 (Sun, 03 Dec 2006) | 10 lines - (pedronis, arigo) more work on Void return values. - nicer logging - add a test using both vlist and vdict, showing an annotation confusion between various types of typedescs. Fixed with a gross hack for now. ------------------------------------------------------------------------ r35118 | arigo | 2006-11-29 13:45:27 +0100 (Wed, 29 Nov 2006) | 7 lines (arre, pedronis, arigo) Be afraid. Very afraid. (pedronis) A branch to experiment with throwing PyPy at the JIT. (arigo) ------------------------------------------------------------------------ Modified: pypy/branch/temp/pypy/rpython/rtyper.py ============================================================================== --- pypy/branch/temp/pypy/rpython/rtyper.py (original) +++ pypy/branch/temp/pypy/rpython/rtyper.py Sat Dec 9 02:31:05 2006 @@ -29,12 +29,12 @@ from pypy.rpython.rmodel import Repr, inputconst, BrokenReprTyperError from pypy.rpython.rmodel import warning, HalfConcreteWrapper from pypy.rpython.annlowlevel import annotate_lowlevel_helper, LowLevelAnnotatorPolicy -from pypy.rpython.rmodel import log from pypy.rpython.typesystem import LowLevelTypeSystem,\ ObjectOrientedTypeSystem class RPythonTyper(object): + from pypy.rpython.rmodel import log def __init__(self, annotator, type_system="lltype"): self.annotator = annotator @@ -77,7 +77,7 @@ try: self.seed = int(os.getenv('RTYPERSEED')) s = 'Using %d as seed for block shuffling' % self.seed - log.info(s) + self.log.info(s) except: self.seed = 0 self.order = None @@ -88,7 +88,7 @@ ## order_module = RTYPERORDER.split(',')[0] ## self.order = __import__(order_module, {}, {}, ['*']).order ## s = 'Using %s.%s for order' % (self.order.__module__, self.order.__name__) -## log.info(s) +## self.log.info(s) self.crash_on_first_typeerror = True def getconfig(self): @@ -224,15 +224,16 @@ error_report = " but %d errors" % self.typererror_count else: error_report = '' - log.event('specializing: %d / %d blocks (%d%%)%s' % ( - n, total, 100 * n // total, error_report)) + self.log.event('specializing: %d / %d blocks (%d%%)%s' % + (n, total, 100 * n // total, error_report)) # make sure all reprs so far have had their setup() called self.call_all_setups() if self.typererrors: self.dump_typererrors(to_log=True) raise TyperError("there were %d error" % len(self.typererrors)) - log.event('-=- specialized %d%s blocks -=-' % (blockcount, newtext)) + self.log.event('-=- specialized %d%s blocks -=-' % ( + blockcount, newtext)) def dump_typererrors(self, num=None, minimize=True, to_log=False): c = 0 @@ -248,13 +249,13 @@ str(err) + "\n") if to_log: - log.ERROR(errmsg) + self.log.ERROR(errmsg) else: print errmsg if bc: minmsg = "(minimized %d errors away for this dump)" % (bc,) if to_log: - log.ERROR(minmsg) + self.log.ERROR(minmsg) else: print minmsg @@ -453,22 +454,19 @@ yield HighLevelOp(self, block.operations[-1], exclinks, llops) def translate_hl_to_ll(self, hop, varmapping): - #log.translating(hop.spaceop.opname, hop.args_s) + #self.log.translating(hop.spaceop.opname, hop.args_s) resultvar = hop.dispatch() if hop.exceptionlinks and hop.llops.llop_raising_exceptions is None: raise TyperError("the graph catches %s, but the rtyper did not " "take exceptions into account " "(exception_is_here() not called)" % ( [link.exitcase.__name__ for link in hop.exceptionlinks],)) - op = hop.spaceop if resultvar is None: # no return value - if hop.s_result != annmodel.SomeImpossibleValue(): - raise TyperError("the annotator doesn't agree that '%s' " - "has no return value" % op.opname) - op.result.concretetype = Void + self.translate_no_return_value(hop) else: assert isinstance(resultvar, (Variable, Constant)) + op = hop.spaceop # for simplicity of the translate_meth, resultvar is usually not # op.result here. We have to replace resultvar with op.result # in all generated operations. @@ -500,6 +498,13 @@ hop.llops.append(SpaceOperation('same_as', [resultvar], op.result)) + def translate_no_return_value(self, hop): + op = hop.spaceop + if hop.s_result != annmodel.s_ImpossibleValue: + raise TyperError("the annotator doesn't agree that '%s' " + "has no return value" % op.opname) + op.result.concretetype = Void + def gottypererror(self, e, block, position, llops): """Record a TyperError without crashing immediately. Put a 'TyperError' operation in the graph instead. From arigo at codespeak.net Sat Dec 9 02:31:12 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 9 Dec 2006 02:31:12 +0100 (CET) Subject: [pypy-svn] r35515 - pypy/branch/temp/pypy/interpreter Message-ID: <20061209013112.3A01C10082@code0.codespeak.net> Author: arigo Date: Sat Dec 9 02:31:07 2006 New Revision: 35515 Modified: pypy/branch/temp/pypy/interpreter/baseobjspace.py Log: merging of http://codespeak.net/svn/pypy/branch/jit-real-world/pypy/interpreter/baseobjspace.py revisions 35112 to 35513: ------------------------------------------------------------------------ r35184 | arigo | 2006-12-01 03:43:34 +0100 (Fri, 01 Dec 2006) | 16 lines (pedronis, arigo) Intermediate check-in #2. More seriously, we rewrote the interpreter main loop in a style that should be easier for the JIT to grasp, but also -- possibly -- easier for human beings to grasp. A bit. Many levels of wrapping of stuff into other stuff are avoided now, and the PyFrame class hierarchy was completely removed. There is a possibly nice way to add opcodes from outside, with config options to enable them. The drawback is that the core main loop uses modern RPython magic. Translation not tested. It makes py.py slower by 30% but we hope that pypy-c will be faster. ------------------------------------------------------------------------ r35118 | arigo | 2006-11-29 13:45:27 +0100 (Wed, 29 Nov 2006) | 7 lines (arre, pedronis, arigo) Be afraid. Very afraid. (pedronis) A branch to experiment with throwing PyPy at the JIT. (arigo) ------------------------------------------------------------------------ Modified: pypy/branch/temp/pypy/interpreter/baseobjspace.py ============================================================================== --- pypy/branch/temp/pypy/interpreter/baseobjspace.py (original) +++ pypy/branch/temp/pypy/interpreter/baseobjspace.py Sat Dec 9 02:31:07 2006 @@ -173,6 +173,10 @@ from pypy.config.pypyoption import get_pypy_config config = get_pypy_config(translating=False) self.config = config + + # import extra modules for side-effects, possibly based on config + import pypy.interpreter.nestedscope # register *_DEREF bytecodes + self.interned_strings = {} self.pending_actions = [] self.setoptions(**kw) From arigo at codespeak.net Sat Dec 9 02:31:18 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 9 Dec 2006 02:31:18 +0100 (CET) Subject: [pypy-svn] r35516 - pypy/branch/temp/pypy/config Message-ID: <20061209013118.8BC1710086@code0.codespeak.net> Author: arigo Date: Sat Dec 9 02:31:15 2006 New Revision: 35516 Modified: pypy/branch/temp/pypy/config/pypyoption.py Log: merging of http://codespeak.net/svn/pypy/branch/jit-real-world/pypy/config/pypyoption.py revisions 35112 to 35513: ------------------------------------------------------------------------ r35184 | arigo | 2006-12-01 03:43:34 +0100 (Fri, 01 Dec 2006) | 16 lines (pedronis, arigo) Intermediate check-in #2. More seriously, we rewrote the interpreter main loop in a style that should be easier for the JIT to grasp, but also -- possibly -- easier for human beings to grasp. A bit. Many levels of wrapping of stuff into other stuff are avoided now, and the PyFrame class hierarchy was completely removed. There is a possibly nice way to add opcodes from outside, with config options to enable them. The drawback is that the core main loop uses modern RPython magic. Translation not tested. It makes py.py slower by 30% but we hope that pypy-c will be faster. ------------------------------------------------------------------------ r35133 | arigo | 2006-11-29 19:13:19 +0100 (Wed, 29 Nov 2006) | 3 lines (pedronis, arre, arigo) Intermediate check-in. ------------------------------------------------------------------------ r35118 | arigo | 2006-11-29 13:45:27 +0100 (Wed, 29 Nov 2006) | 7 lines (arre, pedronis, arigo) Be afraid. Very afraid. (pedronis) A branch to experiment with throwing PyPy at the JIT. (arigo) ------------------------------------------------------------------------ Modified: pypy/branch/temp/pypy/config/pypyoption.py ============================================================================== --- pypy/branch/temp/pypy/config/pypyoption.py (original) +++ pypy/branch/temp/pypy/config/pypyoption.py Sat Dec 9 02:31:15 2006 @@ -36,6 +36,9 @@ ["cpython", "ast"], "ast", cmdline='--compiler'), + OptionDescription("opcodes", "opcodes to enable in the interpreter", [ + ]), + BoolOption("nofaking", "disallow faking in the object space", default=False, requires=[ From arigo at codespeak.net Sat Dec 9 02:31:22 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 9 Dec 2006 02:31:22 +0100 (CET) Subject: [pypy-svn] r35517 - pypy/branch/temp/pypy/annotation Message-ID: <20061209013122.256361007B@code0.codespeak.net> Author: arigo Date: Sat Dec 9 02:31:19 2006 New Revision: 35517 Modified: pypy/branch/temp/pypy/annotation/annrpython.py Log: merging of http://codespeak.net/svn/pypy/branch/jit-real-world/pypy/annotation/annrpython.py revisions 35112 to 35513: ------------------------------------------------------------------------ r35215 | arigo | 2006-12-02 16:45:20 +0100 (Sat, 02 Dec 2006) | 8 lines (pedronis, arigo) - added hints in the new dispatch_bytecode() function - for now, restrict the hint-annotator to a very small subset of PyPy (it ends up seeing ~230 functions including ll helpers) - added a timeshift goal, now that hint-annotation seems to work - more support for Voids in the hint-annotator and the timeshifter ------------------------------------------------------------------------ r35118 | arigo | 2006-11-29 13:45:27 +0100 (Wed, 29 Nov 2006) | 7 lines (arre, pedronis, arigo) Be afraid. Very afraid. (pedronis) A branch to experiment with throwing PyPy at the JIT. (arigo) ------------------------------------------------------------------------ Modified: pypy/branch/temp/pypy/annotation/annrpython.py ============================================================================== --- pypy/branch/temp/pypy/annotation/annrpython.py (original) +++ pypy/branch/temp/pypy/annotation/annrpython.py Sat Dec 9 02:31:19 2006 @@ -737,13 +737,16 @@ graph = self.bookkeeper.position_key[0] raise_nicer_exception(op, str(graph)) if resultcell is None: - resultcell = annmodel.s_ImpossibleValue # no return value + resultcell = self.noreturnvalue(op) elif resultcell == annmodel.s_ImpossibleValue: raise BlockedInference(self, op) # the operation cannot succeed assert isinstance(resultcell, annmodel.SomeObject) assert isinstance(op.result, Variable) self.setbinding(op.result, resultcell) # bind resultcell to op.result + def noreturnvalue(self, op): + return annmodel.s_ImpossibleValue # no return value (hook method) + # XXX "contains" clash with SomeObject method def consider_op_contains(self, seq, elem): self.bookkeeper.count("contains", seq) From arigo at codespeak.net Sat Dec 9 02:31:26 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 9 Dec 2006 02:31:26 +0100 (CET) Subject: [pypy-svn] r35518 - pypy/branch/temp/pypy/tool Message-ID: <20061209013126.D612510087@code0.codespeak.net> Author: arigo Date: Sat Dec 9 02:31:21 2006 New Revision: 35518 Modified: pypy/branch/temp/pypy/tool/error.py Log: merging of http://codespeak.net/svn/pypy/branch/jit-real-world/pypy/tool/error.py revisions 35112 to 35513: ------------------------------------------------------------------------ r35232 | arigo | 2006-12-03 23:18:38 +0100 (Sun, 03 Dec 2006) | 5 lines Even without debugging info, blocked blocks can display meaningful errors because the blocked operation is the first one whose result is not annotated. ------------------------------------------------------------------------ r35118 | arigo | 2006-11-29 13:45:27 +0100 (Wed, 29 Nov 2006) | 7 lines (arre, pedronis, arigo) Be afraid. Very afraid. (pedronis) A branch to experiment with throwing PyPy at the JIT. (arigo) ------------------------------------------------------------------------ Modified: pypy/branch/temp/pypy/tool/error.py ============================================================================== --- pypy/branch/temp/pypy/tool/error.py (original) +++ pypy/branch/temp/pypy/tool/error.py Sat Dec 9 02:31:21 2006 @@ -71,16 +71,26 @@ msg = [""] msg.append('-+' * 30) from pypy.annotation import model + msg.append("Blocked block -- operation cannot succeed") if model.DEBUG: - msg.append("Blocked block -- operation cannot succeed") _, _, operindex = annotator.why_not_annotated[block][1].break_at + else: + # guess the blocked operation by the fact that its return value is + # not annotated + for operindex in range(len(block.operations)): + if block.operations[operindex].result not in annotator.bindings: + break + else: + operindex = None + + if operindex is not None: oper = block.operations[operindex] msg.append(" " + str(oper)) else: - msg.append("Blocked block") - operindex = None + oper = None + msg.append(" (inconsistency - the block is fully annotated??)") msg += source_lines(graph, block, operindex, long=True) - if model.DEBUG: + if oper is not None: if SHOW_ANNOTATIONS: msg.append("Known variable annotations:") for arg in oper.args + [oper.result]: @@ -89,7 +99,7 @@ msg.append(" " + str(arg) + " = " + str(annotator.binding(arg))) except KeyError: pass - if SHOW_TRACEBACK: + if model.DEBUG and SHOW_TRACEBACK: msg.extend(traceback.format_exception(*annotator.why_not_annotated[block])) return "\n".join(msg) From arigo at codespeak.net Sat Dec 9 02:31:30 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 9 Dec 2006 02:31:30 +0100 (CET) Subject: [pypy-svn] r35519 - pypy/branch/temp/pypy/objspace/flow Message-ID: <20061209013130.9F9F810091@code0.codespeak.net> Author: arigo Date: Sat Dec 9 02:31:25 2006 New Revision: 35519 Modified: pypy/branch/temp/pypy/objspace/flow/flowcontext.py Log: merging of http://codespeak.net/svn/pypy/branch/jit-real-world/pypy/objspace/flow/flowcontext.py revisions 35112 to 35513: ------------------------------------------------------------------------ r35184 | arigo | 2006-12-01 03:43:34 +0100 (Fri, 01 Dec 2006) | 16 lines (pedronis, arigo) Intermediate check-in #2. More seriously, we rewrote the interpreter main loop in a style that should be easier for the JIT to grasp, but also -- possibly -- easier for human beings to grasp. A bit. Many levels of wrapping of stuff into other stuff are avoided now, and the PyFrame class hierarchy was completely removed. There is a possibly nice way to add opcodes from outside, with config options to enable them. The drawback is that the core main loop uses modern RPython magic. Translation not tested. It makes py.py slower by 30% but we hope that pypy-c will be faster. ------------------------------------------------------------------------ r35118 | arigo | 2006-11-29 13:45:27 +0100 (Wed, 29 Nov 2006) | 7 lines (arre, pedronis, arigo) Be afraid. Very afraid. (pedronis) A branch to experiment with throwing PyPy at the JIT. (arigo) ------------------------------------------------------------------------ Modified: pypy/branch/temp/pypy/objspace/flow/flowcontext.py ============================================================================== --- pypy/branch/temp/pypy/objspace/flow/flowcontext.py (original) +++ pypy/branch/temp/pypy/objspace/flow/flowcontext.py Sat Dec 9 02:31:25 2006 @@ -95,7 +95,7 @@ def bytecode_trace(self, ec, frame): assert frame is ec.crnt_frame, "seeing an unexpected frame!" - ec.crnt_offset = frame.next_instr # save offset for opcode + ec.crnt_offset = frame.last_instr # save offset for opcode if self.enterspamblock: # If we have a SpamBlock, the first call to bytecode_trace() # occurs as soon as frame.resume() starts, before interpretation @@ -218,8 +218,10 @@ # create an empty frame suitable for the code object # while ignoring any operation like the creation of the locals dict self.recorder = [] - return self.code.create_frame(self.space, self.w_globals, - self.closure) + frame = self.code.create_frame(self.space, self.w_globals, + self.closure) + frame.last_instr = 0 + return frame def bytecode_trace(self, frame): self.recorder.bytecode_trace(self, frame) @@ -256,11 +258,15 @@ except StopFlowing: continue # restarting a dead SpamBlock try: + self.framestack.push(frame) self.crnt_frame = frame try: - w_result = frame.resume() + w_result = frame.dispatch(frame.pycode.co_code, + frame.last_instr, + self) finally: self.crnt_frame = None + self.framestack.pop() except OperationThatShouldNotBePropagatedError, e: raise Exception( From arigo at codespeak.net Sat Dec 9 02:31:34 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 9 Dec 2006 02:31:34 +0100 (CET) Subject: [pypy-svn] r35520 - pypy/branch/temp/pypy/translator/goal Message-ID: <20061209013134.6919710090@code0.codespeak.net> Author: arigo Date: Sat Dec 9 02:31:29 2006 New Revision: 35520 Modified: pypy/branch/temp/pypy/translator/goal/translate.py Log: merging of http://codespeak.net/svn/pypy/branch/jit-real-world/pypy/translator/goal/translate.py revisions 35112 to 35513: ------------------------------------------------------------------------ r35133 | arigo | 2006-11-29 19:13:19 +0100 (Wed, 29 Nov 2006) | 3 lines (pedronis, arre, arigo) Intermediate check-in. ------------------------------------------------------------------------ r35118 | arigo | 2006-11-29 13:45:27 +0100 (Wed, 29 Nov 2006) | 7 lines (arre, pedronis, arigo) Be afraid. Very afraid. (pedronis) A branch to experiment with throwing PyPy at the JIT. (arigo) ------------------------------------------------------------------------ Modified: pypy/branch/temp/pypy/translator/goal/translate.py ============================================================================== --- pypy/branch/temp/pypy/translator/goal/translate.py (original) +++ pypy/branch/temp/pypy/translator/goal/translate.py Sat Dec 9 02:31:29 2006 @@ -158,6 +158,9 @@ existing_config=config, translating=True) + if 'handle_translate_config' in targetspec_dic: + targetspec_dic['handle_translate_config'](translateconfig) + if translateconfig.help: opt_parser.print_help() if 'print_help' in targetspec_dic: From arigo at codespeak.net Sat Dec 9 02:31:36 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 9 Dec 2006 02:31:36 +0100 (CET) Subject: [pypy-svn] r35521 - pypy/branch/temp/pypy/translator/goal Message-ID: <20061209013136.DE6A410094@code0.codespeak.net> Author: arigo Date: Sat Dec 9 02:31:34 2006 New Revision: 35521 Modified: pypy/branch/temp/pypy/translator/goal/targetpypystandalone.py Log: merging of http://codespeak.net/svn/pypy/branch/jit-real-world/pypy/translator/goal/targetpypystandalone.py revisions 35112 to 35513: ------------------------------------------------------------------------ r35133 | arigo | 2006-11-29 19:13:19 +0100 (Wed, 29 Nov 2006) | 3 lines (pedronis, arre, arigo) Intermediate check-in. ------------------------------------------------------------------------ r35118 | arigo | 2006-11-29 13:45:27 +0100 (Wed, 29 Nov 2006) | 7 lines (arre, pedronis, arigo) Be afraid. Very afraid. (pedronis) A branch to experiment with throwing PyPy at the JIT. (arigo) ------------------------------------------------------------------------ Modified: pypy/branch/temp/pypy/translator/goal/targetpypystandalone.py ============================================================================== --- pypy/branch/temp/pypy/translator/goal/targetpypystandalone.py (original) +++ pypy/branch/temp/pypy/translator/goal/targetpypystandalone.py Sat Dec 9 02:31:34 2006 @@ -90,6 +90,9 @@ def handle_config(self, config): pass + def handle_translate_config(self, translateconfig): + pass + def print_help(self, config): self.opt_parser(config).print_help() @@ -154,6 +157,7 @@ def interface(self, ns): for name in ['take_options', 'handle_config', 'print_help', 'target', + 'handle_translate_config', 'get_additional_config_options']: ns[name] = getattr(self, name) From arigo at codespeak.net Sat Dec 9 02:31:43 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 9 Dec 2006 02:31:43 +0100 (CET) Subject: [pypy-svn] r35522 - pypy/branch/temp/pypy/translator/tool Message-ID: <20061209013143.553501009D@code0.codespeak.net> Author: arigo Date: Sat Dec 9 02:31:37 2006 New Revision: 35522 Modified: pypy/branch/temp/pypy/translator/tool/make_dot.py Log: merging of http://codespeak.net/svn/pypy/branch/jit-real-world/pypy/translator/tool/make_dot.py revisions 35112 to 35513: ------------------------------------------------------------------------ r35385 | ac | 2006-12-06 13:32:01 +0100 (Wed, 06 Dec 2006) | 1 line svn merge -r 35383:35384 svn+ssh://codespeak.net/svn/pypy/dist/pypy/translator/tool ------------------------------------------------------------------------ r35301 | arigo | 2006-12-05 15:08:43 +0100 (Tue, 05 Dec 2006) | 9 lines (arre, pedronis, arigo) Dump generated machine code if the PYPYJITLOG env var is set (then it dumps to the file named in $PYPYJITLOG). Improve the viewcode.py viewer to use a fixed-size font and expand the tabs into columns manually. ------------------------------------------------------------------------ r35118 | arigo | 2006-11-29 13:45:27 +0100 (Wed, 29 Nov 2006) | 7 lines (arre, pedronis, arigo) Be afraid. Very afraid. (pedronis) A branch to experiment with throwing PyPy at the JIT. (arigo) ------------------------------------------------------------------------ Modified: pypy/branch/temp/pypy/translator/tool/make_dot.py ============================================================================== --- pypy/branch/temp/pypy/translator/tool/make_dot.py (original) +++ pypy/branch/temp/pypy/translator/tool/make_dot.py Sat Dec 9 02:31:37 2006 @@ -67,10 +67,11 @@ color="black", fillcolor="white", style="filled", + width="0.75", ): d = locals() attrs = [('%s="%s"' % (x, d[x].replace('"', '\\"').replace('\n', '\\n'))) - for x in ['shape', 'label', 'color', 'fillcolor', 'style']] + for x in ['shape', 'label', 'color', 'fillcolor', 'style', 'width']] self.emit('%s [%s];' % (safename(name), ", ".join(attrs))) From arigo at codespeak.net Sat Dec 9 02:34:48 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 9 Dec 2006 02:34:48 +0100 (CET) Subject: [pypy-svn] r35523 - in pypy/branch/jit-real-world/pypy: . annotation bin config config/test doc interpreter interpreter/pyparser jit/codegen/llvm jit/codegen/ppc lang lib module/_dotnet module/posix module/sys module/thread objspace objspace/fake objspace/flow objspace/std/test objspace/test rlib/parsing rpython rpython/lltypesystem rpython/memory rpython/module rpython/ootypesystem rpython/rctypes rpython/test tool tool/build translator translator/backendopt translator/c translator/c/src translator/c/test translator/cli translator/goal translator/js translator/llvm translator/oosupport translator/test translator/tool Message-ID: <20061209013448.734FE10087@code0.codespeak.net> Author: arigo Date: Sat Dec 9 02:34:46 2006 New Revision: 35523 Added: pypy/branch/jit-real-world/pypy/annotation/annrpython.py - copied unchanged from r35513, pypy/branch/temp/pypy/annotation/annrpython.py pypy/branch/jit-real-world/pypy/bin/ - copied from r35513, pypy/branch/temp/pypy/bin/ pypy/branch/jit-real-world/pypy/config/config.py - copied unchanged from r35513, pypy/branch/temp/pypy/config/config.py pypy/branch/jit-real-world/pypy/config/pypyoption.py - copied unchanged from r35513, pypy/branch/temp/pypy/config/pypyoption.py pypy/branch/jit-real-world/pypy/config/test/ - copied from r35513, pypy/branch/temp/pypy/config/test/ pypy/branch/jit-real-world/pypy/config/translationoption.py - copied unchanged from r35513, pypy/branch/temp/pypy/config/translationoption.py pypy/branch/jit-real-world/pypy/conftest.py - copied unchanged from r35513, pypy/branch/temp/pypy/conftest.py pypy/branch/jit-real-world/pypy/doc/ - copied from r35513, pypy/branch/temp/pypy/doc/ pypy/branch/jit-real-world/pypy/interpreter/baseobjspace.py - copied unchanged from r35513, pypy/branch/temp/pypy/interpreter/baseobjspace.py pypy/branch/jit-real-world/pypy/interpreter/pyparser/ - copied from r35513, pypy/branch/temp/pypy/interpreter/pyparser/ pypy/branch/jit-real-world/pypy/jit/codegen/llvm/ - copied from r35513, pypy/branch/temp/pypy/jit/codegen/llvm/ pypy/branch/jit-real-world/pypy/jit/codegen/ppc/rgenop.py - copied unchanged from r35513, pypy/branch/temp/pypy/jit/codegen/ppc/rgenop.py pypy/branch/jit-real-world/pypy/lang/ - copied from r35513, pypy/branch/temp/pypy/lang/ pypy/branch/jit-real-world/pypy/lib/ - copied from r35513, pypy/branch/temp/pypy/lib/ pypy/branch/jit-real-world/pypy/module/_dotnet/ - copied from r35513, pypy/branch/temp/pypy/module/_dotnet/ pypy/branch/jit-real-world/pypy/module/posix/ - copied from r35513, pypy/branch/temp/pypy/module/posix/ pypy/branch/jit-real-world/pypy/module/sys/ - copied from r35513, pypy/branch/temp/pypy/module/sys/ pypy/branch/jit-real-world/pypy/module/thread/ - copied from r35513, pypy/branch/temp/pypy/module/thread/ pypy/branch/jit-real-world/pypy/objspace/fake/ - copied from r35513, pypy/branch/temp/pypy/objspace/fake/ pypy/branch/jit-real-world/pypy/objspace/flow/flowcontext.py - copied unchanged from r35513, pypy/branch/temp/pypy/objspace/flow/flowcontext.py pypy/branch/jit-real-world/pypy/objspace/logic.py - copied unchanged from r35513, pypy/branch/temp/pypy/objspace/logic.py pypy/branch/jit-real-world/pypy/objspace/std/test/ - copied from r35513, pypy/branch/temp/pypy/objspace/std/test/ pypy/branch/jit-real-world/pypy/objspace/test/ - copied from r35513, pypy/branch/temp/pypy/objspace/test/ pypy/branch/jit-real-world/pypy/rlib/parsing/ - copied from r35513, pypy/branch/temp/pypy/rlib/parsing/ pypy/branch/jit-real-world/pypy/rpython/extfunctable.py - copied unchanged from r35513, pypy/branch/temp/pypy/rpython/extfunctable.py pypy/branch/jit-real-world/pypy/rpython/lltypesystem/rpbc.py - copied unchanged from r35513, pypy/branch/temp/pypy/rpython/lltypesystem/rpbc.py pypy/branch/jit-real-world/pypy/rpython/memory/ - copied from r35513, pypy/branch/temp/pypy/rpython/memory/ pypy/branch/jit-real-world/pypy/rpython/module/ - copied from r35513, pypy/branch/temp/pypy/rpython/module/ pypy/branch/jit-real-world/pypy/rpython/ootypesystem/rclass.py - copied unchanged from r35513, pypy/branch/temp/pypy/rpython/ootypesystem/rclass.py pypy/branch/jit-real-world/pypy/rpython/rctypes/ - copied from r35513, pypy/branch/temp/pypy/rpython/rctypes/ pypy/branch/jit-real-world/pypy/rpython/rexternalobj.py - copied unchanged from r35513, pypy/branch/temp/pypy/rpython/rexternalobj.py pypy/branch/jit-real-world/pypy/rpython/rpbc.py - copied unchanged from r35513, pypy/branch/temp/pypy/rpython/rpbc.py pypy/branch/jit-real-world/pypy/rpython/rtyper.py - copied unchanged from r35513, pypy/branch/temp/pypy/rpython/rtyper.py pypy/branch/jit-real-world/pypy/rpython/test/test_exception.py - copied unchanged from r35513, pypy/branch/temp/pypy/rpython/test/test_exception.py pypy/branch/jit-real-world/pypy/rpython/test/test_llinterp.py - copied unchanged from r35513, pypy/branch/temp/pypy/rpython/test/test_llinterp.py pypy/branch/jit-real-world/pypy/rpython/test/test_rpbc.py - copied unchanged from r35513, pypy/branch/temp/pypy/rpython/test/test_rpbc.py pypy/branch/jit-real-world/pypy/tool/build/ - copied from r35513, pypy/branch/temp/pypy/tool/build/ pypy/branch/jit-real-world/pypy/tool/error.py - copied unchanged from r35513, pypy/branch/temp/pypy/tool/error.py pypy/branch/jit-real-world/pypy/tool/option.py - copied unchanged from r35513, pypy/branch/temp/pypy/tool/option.py pypy/branch/jit-real-world/pypy/translator/backendopt/ - copied from r35513, pypy/branch/temp/pypy/translator/backendopt/ pypy/branch/jit-real-world/pypy/translator/c/exceptiontransform.py - copied unchanged from r35513, pypy/branch/temp/pypy/translator/c/exceptiontransform.py pypy/branch/jit-real-world/pypy/translator/c/extfunc.py - copied unchanged from r35513, pypy/branch/temp/pypy/translator/c/extfunc.py pypy/branch/jit-real-world/pypy/translator/c/genc.py - copied unchanged from r35513, pypy/branch/temp/pypy/translator/c/genc.py pypy/branch/jit-real-world/pypy/translator/c/primitive.py - copied unchanged from r35513, pypy/branch/temp/pypy/translator/c/primitive.py pypy/branch/jit-real-world/pypy/translator/c/src/ - copied from r35513, pypy/branch/temp/pypy/translator/c/src/ pypy/branch/jit-real-world/pypy/translator/c/test/ - copied from r35513, pypy/branch/temp/pypy/translator/c/test/ pypy/branch/jit-real-world/pypy/translator/cli/ - copied from r35513, pypy/branch/temp/pypy/translator/cli/ pypy/branch/jit-real-world/pypy/translator/driver.py - copied unchanged from r35513, pypy/branch/temp/pypy/translator/driver.py pypy/branch/jit-real-world/pypy/translator/goal/app_main.py - copied unchanged from r35513, pypy/branch/temp/pypy/translator/goal/app_main.py pypy/branch/jit-real-world/pypy/translator/goal/bench-cronjob.py - copied unchanged from r35513, pypy/branch/temp/pypy/translator/goal/bench-cronjob.py pypy/branch/jit-real-world/pypy/translator/goal/bench-custom.py - copied unchanged from r35513, pypy/branch/temp/pypy/translator/goal/bench-custom.py pypy/branch/jit-real-world/pypy/translator/goal/bench-unix.py - copied unchanged from r35513, pypy/branch/temp/pypy/translator/goal/bench-unix.py pypy/branch/jit-real-world/pypy/translator/goal/targetmultiplespaces.py - copied unchanged from r35513, pypy/branch/temp/pypy/translator/goal/targetmultiplespaces.py pypy/branch/jit-real-world/pypy/translator/goal/targetpypystandalone.py - copied unchanged from r35513, pypy/branch/temp/pypy/translator/goal/targetpypystandalone.py pypy/branch/jit-real-world/pypy/translator/goal/translate.py - copied unchanged from r35513, pypy/branch/temp/pypy/translator/goal/translate.py pypy/branch/jit-real-world/pypy/translator/interactive.py - copied unchanged from r35513, pypy/branch/temp/pypy/translator/interactive.py pypy/branch/jit-real-world/pypy/translator/js/ - copied from r35513, pypy/branch/temp/pypy/translator/js/ pypy/branch/jit-real-world/pypy/translator/llvm/ - copied from r35513, pypy/branch/temp/pypy/translator/llvm/ pypy/branch/jit-real-world/pypy/translator/oosupport/ - copied from r35513, pypy/branch/temp/pypy/translator/oosupport/ pypy/branch/jit-real-world/pypy/translator/test/ - copied from r35513, pypy/branch/temp/pypy/translator/test/ pypy/branch/jit-real-world/pypy/translator/tool/make_dot.py - copied unchanged from r35513, pypy/branch/temp/pypy/translator/tool/make_dot.py pypy/branch/jit-real-world/pypy/translator/tool/raymond.py - copied unchanged from r35513, pypy/branch/temp/pypy/translator/tool/raymond.py pypy/branch/jit-real-world/pypy/translator/translator.py - copied unchanged from r35513, pypy/branch/temp/pypy/translator/translator.py Log: (pedronis, arigo) Merge the trunk into the jit-real-world branch, which is going to become the trunk... From arigo at codespeak.net Sat Dec 9 02:52:44 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 9 Dec 2006 02:52:44 +0100 (CET) Subject: [pypy-svn] r35525 - pypy/branch/jit-real-world Message-ID: <20061209015244.682E210088@code0.codespeak.net> Author: arigo Date: Sat Dec 9 02:52:44 2006 New Revision: 35525 Added: pypy/branch/jit-real-world/ - copied from r35522, pypy/branch/jit-real-world/ Log: (pedronis, arigo) Restoring the branch at the state just before things went wrong From arigo at codespeak.net Sat Dec 9 02:53:42 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 9 Dec 2006 02:53:42 +0100 (CET) Subject: [pypy-svn] r35526 - in pypy/branch/jit-real-world/pypy: . annotation bin config config/test doc interpreter interpreter/pyparser jit/codegen/llvm jit/codegen/ppc lang lib module/_dotnet module/posix module/sys module/thread objspace objspace/fake objspace/flow objspace/std/test objspace/test rlib/parsing rpython rpython/lltypesystem rpython/memory rpython/module rpython/ootypesystem rpython/rctypes rpython/test tool tool/build translator translator/backendopt translator/c translator/c/src translator/c/test translator/cli translator/goal translator/js translator/llvm translator/oosupport translator/test translator/tool Message-ID: <20061209015342.0051510089@code0.codespeak.net> Author: arigo Date: Sat Dec 9 02:53:42 2006 New Revision: 35526 Added: pypy/branch/jit-real-world/pypy/annotation/annrpython.py - copied unchanged from r35525, pypy/branch/temp/pypy/annotation/annrpython.py pypy/branch/jit-real-world/pypy/bin/ - copied from r35525, pypy/branch/temp/pypy/bin/ pypy/branch/jit-real-world/pypy/config/config.py - copied unchanged from r35525, pypy/branch/temp/pypy/config/config.py pypy/branch/jit-real-world/pypy/config/pypyoption.py - copied unchanged from r35525, pypy/branch/temp/pypy/config/pypyoption.py pypy/branch/jit-real-world/pypy/config/test/ - copied from r35525, pypy/branch/temp/pypy/config/test/ pypy/branch/jit-real-world/pypy/config/translationoption.py - copied unchanged from r35525, pypy/branch/temp/pypy/config/translationoption.py pypy/branch/jit-real-world/pypy/conftest.py - copied unchanged from r35525, pypy/branch/temp/pypy/conftest.py pypy/branch/jit-real-world/pypy/doc/ - copied from r35525, pypy/branch/temp/pypy/doc/ pypy/branch/jit-real-world/pypy/interpreter/baseobjspace.py - copied unchanged from r35525, pypy/branch/temp/pypy/interpreter/baseobjspace.py pypy/branch/jit-real-world/pypy/interpreter/pyparser/ - copied from r35525, pypy/branch/temp/pypy/interpreter/pyparser/ pypy/branch/jit-real-world/pypy/jit/codegen/llvm/ - copied from r35525, pypy/branch/temp/pypy/jit/codegen/llvm/ pypy/branch/jit-real-world/pypy/jit/codegen/ppc/rgenop.py - copied unchanged from r35525, pypy/branch/temp/pypy/jit/codegen/ppc/rgenop.py pypy/branch/jit-real-world/pypy/lang/ - copied from r35525, pypy/branch/temp/pypy/lang/ pypy/branch/jit-real-world/pypy/lib/ - copied from r35525, pypy/branch/temp/pypy/lib/ pypy/branch/jit-real-world/pypy/module/_dotnet/ - copied from r35525, pypy/branch/temp/pypy/module/_dotnet/ pypy/branch/jit-real-world/pypy/module/posix/ - copied from r35525, pypy/branch/temp/pypy/module/posix/ pypy/branch/jit-real-world/pypy/module/sys/ - copied from r35525, pypy/branch/temp/pypy/module/sys/ pypy/branch/jit-real-world/pypy/module/thread/ - copied from r35525, pypy/branch/temp/pypy/module/thread/ pypy/branch/jit-real-world/pypy/objspace/fake/ - copied from r35525, pypy/branch/temp/pypy/objspace/fake/ pypy/branch/jit-real-world/pypy/objspace/flow/flowcontext.py - copied unchanged from r35525, pypy/branch/temp/pypy/objspace/flow/flowcontext.py pypy/branch/jit-real-world/pypy/objspace/logic.py - copied unchanged from r35525, pypy/branch/temp/pypy/objspace/logic.py pypy/branch/jit-real-world/pypy/objspace/std/test/ - copied from r35525, pypy/branch/temp/pypy/objspace/std/test/ pypy/branch/jit-real-world/pypy/objspace/test/ - copied from r35525, pypy/branch/temp/pypy/objspace/test/ pypy/branch/jit-real-world/pypy/rlib/parsing/ - copied from r35525, pypy/branch/temp/pypy/rlib/parsing/ pypy/branch/jit-real-world/pypy/rpython/extfunctable.py - copied unchanged from r35525, pypy/branch/temp/pypy/rpython/extfunctable.py pypy/branch/jit-real-world/pypy/rpython/lltypesystem/rpbc.py - copied unchanged from r35525, pypy/branch/temp/pypy/rpython/lltypesystem/rpbc.py pypy/branch/jit-real-world/pypy/rpython/memory/ - copied from r35525, pypy/branch/temp/pypy/rpython/memory/ pypy/branch/jit-real-world/pypy/rpython/module/ - copied from r35525, pypy/branch/temp/pypy/rpython/module/ pypy/branch/jit-real-world/pypy/rpython/ootypesystem/rclass.py - copied unchanged from r35525, pypy/branch/temp/pypy/rpython/ootypesystem/rclass.py pypy/branch/jit-real-world/pypy/rpython/rctypes/ - copied from r35525, pypy/branch/temp/pypy/rpython/rctypes/ pypy/branch/jit-real-world/pypy/rpython/rexternalobj.py - copied unchanged from r35525, pypy/branch/temp/pypy/rpython/rexternalobj.py pypy/branch/jit-real-world/pypy/rpython/rpbc.py - copied unchanged from r35525, pypy/branch/temp/pypy/rpython/rpbc.py pypy/branch/jit-real-world/pypy/rpython/rtyper.py - copied unchanged from r35525, pypy/branch/temp/pypy/rpython/rtyper.py pypy/branch/jit-real-world/pypy/rpython/test/test_exception.py - copied unchanged from r35525, pypy/branch/temp/pypy/rpython/test/test_exception.py pypy/branch/jit-real-world/pypy/rpython/test/test_llinterp.py - copied unchanged from r35525, pypy/branch/temp/pypy/rpython/test/test_llinterp.py pypy/branch/jit-real-world/pypy/rpython/test/test_rpbc.py - copied unchanged from r35525, pypy/branch/temp/pypy/rpython/test/test_rpbc.py pypy/branch/jit-real-world/pypy/tool/build/ - copied from r35525, pypy/branch/temp/pypy/tool/build/ pypy/branch/jit-real-world/pypy/tool/error.py - copied unchanged from r35525, pypy/branch/temp/pypy/tool/error.py pypy/branch/jit-real-world/pypy/tool/option.py - copied unchanged from r35525, pypy/branch/temp/pypy/tool/option.py pypy/branch/jit-real-world/pypy/translator/backendopt/ - copied from r35525, pypy/branch/temp/pypy/translator/backendopt/ pypy/branch/jit-real-world/pypy/translator/c/exceptiontransform.py - copied unchanged from r35525, pypy/branch/temp/pypy/translator/c/exceptiontransform.py pypy/branch/jit-real-world/pypy/translator/c/extfunc.py - copied unchanged from r35525, pypy/branch/temp/pypy/translator/c/extfunc.py pypy/branch/jit-real-world/pypy/translator/c/genc.py - copied unchanged from r35525, pypy/branch/temp/pypy/translator/c/genc.py pypy/branch/jit-real-world/pypy/translator/c/primitive.py - copied unchanged from r35525, pypy/branch/temp/pypy/translator/c/primitive.py pypy/branch/jit-real-world/pypy/translator/c/src/ - copied from r35525, pypy/branch/temp/pypy/translator/c/src/ pypy/branch/jit-real-world/pypy/translator/c/test/ - copied from r35525, pypy/branch/temp/pypy/translator/c/test/ pypy/branch/jit-real-world/pypy/translator/cli/ - copied from r35525, pypy/branch/temp/pypy/translator/cli/ pypy/branch/jit-real-world/pypy/translator/driver.py - copied unchanged from r35525, pypy/branch/temp/pypy/translator/driver.py pypy/branch/jit-real-world/pypy/translator/goal/app_main.py - copied unchanged from r35525, pypy/branch/temp/pypy/translator/goal/app_main.py pypy/branch/jit-real-world/pypy/translator/goal/bench-cronjob.py - copied unchanged from r35525, pypy/branch/temp/pypy/translator/goal/bench-cronjob.py pypy/branch/jit-real-world/pypy/translator/goal/bench-custom.py - copied unchanged from r35525, pypy/branch/temp/pypy/translator/goal/bench-custom.py pypy/branch/jit-real-world/pypy/translator/goal/bench-unix.py - copied unchanged from r35525, pypy/branch/temp/pypy/translator/goal/bench-unix.py pypy/branch/jit-real-world/pypy/translator/goal/targetmultiplespaces.py - copied unchanged from r35525, pypy/branch/temp/pypy/translator/goal/targetmultiplespaces.py pypy/branch/jit-real-world/pypy/translator/goal/targetpypystandalone.py - copied unchanged from r35525, pypy/branch/temp/pypy/translator/goal/targetpypystandalone.py pypy/branch/jit-real-world/pypy/translator/goal/translate.py - copied unchanged from r35525, pypy/branch/temp/pypy/translator/goal/translate.py pypy/branch/jit-real-world/pypy/translator/interactive.py - copied unchanged from r35525, pypy/branch/temp/pypy/translator/interactive.py pypy/branch/jit-real-world/pypy/translator/js/ - copied from r35525, pypy/branch/temp/pypy/translator/js/ pypy/branch/jit-real-world/pypy/translator/llvm/ - copied from r35525, pypy/branch/temp/pypy/translator/llvm/ pypy/branch/jit-real-world/pypy/translator/oosupport/ - copied from r35525, pypy/branch/temp/pypy/translator/oosupport/ pypy/branch/jit-real-world/pypy/translator/test/ - copied from r35525, pypy/branch/temp/pypy/translator/test/ pypy/branch/jit-real-world/pypy/translator/tool/make_dot.py - copied unchanged from r35525, pypy/branch/temp/pypy/translator/tool/make_dot.py pypy/branch/jit-real-world/pypy/translator/tool/raymond.py - copied unchanged from r35525, pypy/branch/temp/pypy/translator/tool/raymond.py pypy/branch/jit-real-world/pypy/translator/translator.py - copied unchanged from r35525, pypy/branch/temp/pypy/translator/translator.py Log: pedronis and arigo trying to merge again... From arigo at codespeak.net Sat Dec 9 02:58:49 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 9 Dec 2006 02:58:49 +0100 (CET) Subject: [pypy-svn] r35528 - pypy/branch/jit-real-world Message-ID: <20061209015849.E391210078@code0.codespeak.net> Author: arigo Date: Sat Dec 9 02:58:49 2006 New Revision: 35528 Removed: pypy/branch/jit-real-world/ Log: Remove the branch. From niko at codespeak.net Sat Dec 9 08:35:05 2006 From: niko at codespeak.net (niko at codespeak.net) Date: Sat, 9 Dec 2006 08:35:05 +0100 (CET) Subject: [pypy-svn] r35533 - in pypy/dist/pypy/translator/jvm: . src test Message-ID: <20061209073505.E01331006F@code0.codespeak.net> Author: niko Date: Sat Dec 9 08:35:03 2006 New Revision: 35533 Added: pypy/dist/pypy/translator/jvm/src/ExceptionWrapper.java Modified: pypy/dist/pypy/translator/jvm/database.py pypy/dist/pypy/translator/jvm/generator.py pypy/dist/pypy/translator/jvm/genjvm.py pypy/dist/pypy/translator/jvm/node.py pypy/dist/pypy/translator/jvm/src/PyPy.java pypy/dist/pypy/translator/jvm/test/runtest.py pypy/dist/pypy/translator/jvm/typesystem.py Log: put in the "least resistance" way to make exceptions work: introduce a wrapper class that descends from RuntimeException. we can improve it later either by not using exception mechanism at all or by making it possible for RPython exceptions to descend from Throwable Modified: pypy/dist/pypy/translator/jvm/database.py ============================================================================== --- pypy/dist/pypy/translator/jvm/database.py (original) +++ pypy/dist/pypy/translator/jvm/database.py Sat Dec 9 08:35:03 2006 @@ -100,10 +100,8 @@ assert OOTYPE._superclass supercls = self.pending_class(OOTYPE._superclass) - # TODO --- make package of java class reflect the package of the - # OO class? - clsnm = self._pkg( - self._uniq(OOTYPE._name.replace('.','_'))) + # Create the class object + clsnm = self._pkg(self._uniq(OOTYPE._name)) clsobj = node.Class(clsnm, supercls) print "Class %s has super %s" % ( Modified: pypy/dist/pypy/translator/jvm/generator.py ============================================================================== --- pypy/dist/pypy/translator/jvm/generator.py (original) +++ pypy/dist/pypy/translator/jvm/generator.py Sat Dec 9 08:35:03 2006 @@ -6,12 +6,7 @@ from pypy.translator.jvm.typesystem import \ JvmType, jString, jInt, jLong, jDouble, jBool, jString, \ jPyPy, jVoid, jMath, desc_for_method, jPrintStream, jClass, jChar, \ - jObject, jByteArray - -# ___________________________________________________________________________ -# Helper class string constants - -PYPYJAVA = jPyPy.name + jObject, jByteArray, jPyPyExcWrap # ___________________________________________________________________________ # Miscellaneous helper functions @@ -236,6 +231,7 @@ DUP2 = Opcode('dup2') POP = Opcode('pop') POP2 = Opcode('pop2') +SWAP = Opcode('swap') INSTANCEOF= IntClassNameOpcode('instanceof') # Loading/storing local variables LOAD = OpcodeFamily(VarOpcode, "load") @@ -353,9 +349,12 @@ PYPYDUMPBOOLEAN = Method.s(jPyPy, 'dump_boolean', (jBool,jInt), jVoid) PYPYDUMPOBJECT = Method.s(jPyPy, 'dump_object', (jObject,jInt,), jVoid) PYPYDUMPVOID = Method.s(jPyPy, 'dump_void', (jInt,), jVoid) +PYPYDUMPEXCWRAPPER = Method.s(jPyPy, 'dump_exc_wrapper', (jObject,), jVoid) PYPYRUNTIMENEW = Method.s(jPyPy, 'RuntimeNew', (jClass,), jObject) PYPYSTRING2BYTES = Method.s(jPyPy, 'string2bytes', (jString,), jByteArray) - +OBJECTGETCLASS = Method.v(jObject, 'getClass', (), jClass) +CLASSGETNAME = Method.v(jClass, 'getName', (), jString) +EXCWRAPWRAP = Method.s(jPyPyExcWrap, 'wrap', (jObject,), jPyPyExcWrap) # ___________________________________________________________________________ # Fields @@ -391,6 +390,8 @@ DOUBLEPOSINF = Field('java.lang.Double', 'POSITIVE_INFINITY', jDouble, True) DOUBLENEGINF = Field('java.lang.Double', 'NEGATIVE_INFINITY', jDouble, True) +EXCWRAPOBJ = Field(jPyPyExcWrap.name, 'object', jObject, False) + # ___________________________________________________________________________ # Generator State @@ -557,6 +558,13 @@ """ Returns a value from top of stack of the JvmType 'vartype' """ self._instr(RETURN.for_type(vartype)) + def load_class_name(self): + """ Loads the name of the *Java* class of the object on the top of + the stack as a Java string. Note that the result for a PyPy + generated class will look something like 'pypy.some.pkg.cls' """ + self.emit(OBJECTGETCLASS) + self.emit(CLASSGETNAME) + def load_string(self, str): """ Pushes a Java version of a Python string onto the stack. 'str' should be a Python string encoded in UTF-8 (I think) """ @@ -647,10 +655,24 @@ try region is reused. 'excclsty' --- a JvmType for the class of exception to be caught """ - catchlbl = self.unique_label("catch") - self.mark(catchlbl, mark=True) - self.try_catch_region( - excclsty, self.begintrylbl, send.endtrylbl, catchlbl) + catchlbl = self.unique_label("catch", mark=True) + self._try_catch_region( + jPyPyExcWrap, self.begintrylbl, self.endtrylbl, catchlbl) + + # emit the code to unwrap the exception, check the type + # of the unwrapped object, and re-throw the exception + # if it not the right type + catch = self.unique_label('catch') + self.emit(DUP) + EXCWRAPOBJ.load(self) + self.emit(INSTANCEOF, excclsty) + self.emit(IFNE, catch) + self.emit(ATHROW) + + # If it IS the right type, just dereference and get the + # wrapped Python object + self.mark(catch) + EXCWRAPOBJ.load(self) def end_catch(self): """ @@ -659,7 +681,7 @@ """ return - def try_catch_region(self, excclsty, trystartlbl, tryendlbl, catchlbl): + def _try_catch_region(self, excclsty, trystartlbl, tryendlbl, catchlbl): """ Indicates a try/catch region: 'excclsty' --- a JvmType for the class of exception to be caught @@ -737,7 +759,7 @@ self._instr(INSTANCEOF, jtype) def branch_unconditionally(self, target_label): - self._instr(GOTO, target_label) + self.goto(target_label) def branch_conditionally(self, cond, target_label): if cond: @@ -846,6 +868,12 @@ def throw(self): """ Throw the object from top of the stack as an exception """ + + # We have to deal with the problem that exceptions must + # derive from Throwable, but our exception hierarchy in OOTYPE + # does not (today). For now, we use a wrapper class, which is + # probably the worst answer of all, but an easy one. + self.emit(EXCWRAPWRAP) self._instr(ATHROW) def iabs(self): @@ -859,6 +887,10 @@ self._instr(ICONST, -1) self._instr(IXOR) + def goto(self, label): + """ Jumps unconditionally """ + self._instr(GOTO, label) + def goto_if_true(self, label): """ Jumps if the top of stack is true """ self._instr(IFNE, label) @@ -1016,7 +1048,10 @@ instr_text, self.curfunc.instr_counter)) self.curfunc.instr_counter+=1 - def try_catch_region(self, excclsty, trystartlbl, tryendlbl, catchlbl): + def _try_catch_region(self, excclsty, trystartlbl, tryendlbl, catchlbl): self.curclass.out(' .catch %s from %s to %s using %s\n' % ( - excclsty.int_class_name(), trystartlbl, tryendlbl, catchlbl)) + excclsty.descriptor.int_class_name(), + trystartlbl.jasmin_syntax(), + tryendlbl.jasmin_syntax(), + catchlbl.jasmin_syntax())) Modified: pypy/dist/pypy/translator/jvm/genjvm.py ============================================================================== --- pypy/dist/pypy/translator/jvm/genjvm.py (original) +++ pypy/dist/pypy/translator/jvm/genjvm.py Sat Dec 9 08:35:03 2006 @@ -94,28 +94,32 @@ raise JvmSubprogramError(res, args, stdout, stderr) return stdout, stderr - def compile(self): - """ - Compiles the .java sources into .class files, ready for execution. - """ - jascmd = [getoption('jasmin'), '-d', str(self.javadir)] - for jasfile in self.jasmin_files: - print "Invoking jasmin on %s" % jasfile - self._invoke(jascmd+[jasfile], False) - + def _compile_helper(self, clsnm): # HACK: compile the Java helper class. Should eventually # use rte.py - pypycls = self.classdir.join('PyPy.class') + pypycls = self.classdir.join(clsnm + '.class') if not os.path.exists(str(pypycls)): sl = __file__.rindex('/') - javasrc = __file__[:sl]+"/src/PyPy.java" + javasrc = __file__[:sl]+("/src/%s.java" % clsnm) self._invoke([getoption('javac'), '-nowarn', '-d', str(self.classdir), javasrc], True) + + + def compile(self): + """ + Compiles the .java sources into .class files, ready for execution. + """ + jascmd = [getoption('jasmin'), '-d', str(self.javadir)] + for jasfile in self.jasmin_files: + print "Invoking jasmin on %s" % jasfile + self._invoke(jascmd+[jasfile], False) self.compiled = True + self._compile_helper('PyPy') + self._compile_helper('ExceptionWrapper') def execute(self, args): """ Modified: pypy/dist/pypy/translator/jvm/node.py ============================================================================== --- pypy/dist/pypy/translator/jvm/node.py (original) +++ pypy/dist/pypy/translator/jvm/node.py Sat Dec 9 08:35:03 2006 @@ -78,6 +78,9 @@ gen.begin_function( 'main', (), [jStringArray], jVoid, static=True) + if self.print_result: + gen.begin_try() + # Handle arguments: if self.expand_arguments: # Convert each entry into the array to the desired type by @@ -101,11 +104,25 @@ gen.emit(self.db.pending_function(self.graph)) # Print result? + # + # Use the dump method for non-exceptional results + # + # For exceptions, just print the runtime type + # if self.print_result: + done_printing = gen.unique_label('done_printing') gen.emit(jvmgen.ICONST, 0) RESOOTYPE = self.graph.getreturnvar().concretetype dumpmethod = self.db.generate_dump_method_for_ootype(RESOOTYPE) dumpmethod.invoke(gen) + gen.goto(done_printing) + gen.end_try() + + gen.begin_catch(jObject) + gen.emit(jvmgen.PYPYDUMPEXCWRAPPER) + gen.end_catch() + + gen.mark(done_printing) # And finish up gen.return_val(jVoid) Added: pypy/dist/pypy/translator/jvm/src/ExceptionWrapper.java ============================================================================== --- (empty file) +++ pypy/dist/pypy/translator/jvm/src/ExceptionWrapper.java Sat Dec 9 08:35:03 2006 @@ -0,0 +1,13 @@ +package pypy; + +public class ExceptionWrapper extends RuntimeException { + public final Object object; + + ExceptionWrapper (Object object) { + this.object = object; + } + + public static ExceptionWrapper wrap(Object object) { + return new ExceptionWrapper(object); + } +} \ No newline at end of file Modified: pypy/dist/pypy/translator/jvm/src/PyPy.java ============================================================================== --- pypy/dist/pypy/translator/jvm/src/PyPy.java (original) +++ pypy/dist/pypy/translator/jvm/src/PyPy.java Sat Dec 9 08:35:03 2006 @@ -245,7 +245,7 @@ dump_indented(indent, sb.toString()); } - public static void dump_string(String b, int indent) { + public static String escaped_string(String b) { StringBuffer sb = new StringBuffer(); sb.append('"'); for (int i = 0; i < b.length(); i++) { @@ -253,13 +253,29 @@ _append_char(sb, c); } sb.append('"'); - dump_indented(indent, sb.toString()); + return sb.toString(); + } + + public static void dump_string(String b, int indent) { + dump_indented(indent, escaped_string(b)); } public static void dump_object(Object o, int indent) { dump_indented(indent, o.toString()); } + // used in running unit tests + // not really part of the dump_XXX set of objects, hence the lack + // of an indent parameter + public static void dump_exc_wrapper(Object o) { + String clnm = o.getClass().getName(); + StringBuffer sb = new StringBuffer(); + sb.append("ExceptionWrapper("); + sb.append(escaped_string(clnm)); + sb.append(")"); + dump_indented(0, sb.toString()); + } + // ---------------------------------------------------------------------- // StringBuffer @@ -354,6 +370,27 @@ } // ---------------------------------------------------------------------- + // Exceptions + // + // If we don't use true Java exceptions, then this + +/* + static private ThreadLocal excObject = new ThreadLocal(); + + public static int startTry() { + return excCounter.get(); + } + + public void throw(Object o) { + excObject.put(o); + } + + public static Object catch(int ctr) { + return excObject.get(); + } +*/ + + // ---------------------------------------------------------------------- // Self Test public static int __counter = 0, __failures = 0; 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 Sat Dec 9 08:35:03 2006 @@ -35,7 +35,14 @@ # CLI duplicate class ExceptionWrapper: def __init__(self, class_name): - self.class_name = class_name + # We put all of our classes into some package like 'pypy': + # strip the initial 'pypy.' that results from the class name, + # and we append a number to make the class name unique. Strip + # those. + pkg = getoption('package')+'.' + assert class_name.startswith(pkg) + uniqidx = class_name.rindex('_') + self.class_name = class_name[len(pkg):uniqidx] def __repr__(self): return 'ExceptionWrapper(%s)' % repr(self.class_name) Modified: pypy/dist/pypy/translator/jvm/typesystem.py ============================================================================== --- pypy/dist/pypy/translator/jvm/typesystem.py (original) +++ pypy/dist/pypy/translator/jvm/typesystem.py Sat Dec 9 08:35:03 2006 @@ -173,6 +173,7 @@ jMath = JvmClassType('java.lang.Math') jList = JvmClassType('java.util.List') jPyPy = JvmClassType('pypy.PyPy') +jPyPyExcWrap = JvmClassType('pypy.ExceptionWrapper') jPyPyConst = JvmClassType('pypy.Constant') jPyPyMain = JvmClassType('pypy.Main') From ericvrp at codespeak.net Sat Dec 9 17:18:13 2006 From: ericvrp at codespeak.net (ericvrp at codespeak.net) Date: Sat, 9 Dec 2006 17:18:13 +0100 (CET) Subject: [pypy-svn] r35538 - in pypy/dist/pypy/jit/codegen/llvm: . test Message-ID: <20061209161813.A4AE510071@code0.codespeak.net> Author: ericvrp Date: Sat Dec 9 17:18:11 2006 New Revision: 35538 Modified: pypy/dist/pypy/jit/codegen/llvm/rgenop.py pypy/dist/pypy/jit/codegen/llvm/test/test_rgenop.py Log: (arigo, ericvrp a very little) Refactoring by arigo to have the llvm JIT backend reflect the llgraph backend more. Until now the llvm backend was losely based on both the i386 and ppc backend. * phi nodes are now correctly inserted in the code. * no longer using alloca. This causes bad code when not using llvm's optimizations. * keeps track of variable types (bool and int at the moment) * op_int_is_true fixed (trunc instruction replaced by setne) * 6 more tests pass. Only the switch and switch_large tests failing at the moment. Modified: pypy/dist/pypy/jit/codegen/llvm/rgenop.py ============================================================================== --- pypy/dist/pypy/jit/codegen/llvm/rgenop.py (original) +++ pypy/dist/pypy/jit/codegen/llvm/rgenop.py Sat Dec 9 17:18:11 2006 @@ -15,49 +15,40 @@ n_vars = 0 n_labels = 0 + def newlabel(self): + label = 'L%d' % (self.n_labels,) + self.n_labels += 1 + return label + count = Count() class Var(GenVar): - def __init__(self): - self.name = '%v' + str(count.n_vars) + def __init__(self, type): + self.n = count.n_vars + self.type = type count.n_vars += 1 def operand(self): - return self.type() + ' ' + self.name + return '%s %%v%d' % (self.type, self.n) def operand2(self): - return self.name - - def type(self): - return 'int' - - -class VarAddr(Var): - - def __init__(self, v, asm): - self.name = '%p' + v.name[2:] - asm.append(' %s=alloca %s' % (self.operand2(), v.type())) #note: sideeffect! - - def type(self): - return 'int*' + return '%%v%d' % (self.n,) class IntConst(GenConst): + type = 'int' def __init__(self, value): self.value = value def operand(self): - return self.type() + ' ' + str(self.value) + return '%s %s' % (self.type, self.value) def operand2(self): return str(self.value) - def type(self): - return 'int' - @specialize.arg(1) def revealconst(self, T): if isinstance(T, lltype.Ptr): @@ -69,19 +60,17 @@ class AddrConst(GenConst): + type = 'int*' def __init__(self, addr): self.addr = addr def operand(self): - return self.type() + ' ' + str(llmemory.cast_adr_to_int(self.addr)) + return '%s %s' % (self.type, llmemory.cast_adr_to_int(self.addr)) def operand2(self): return str(llmemory.cast_adr_to_int(self.addr)) - def type(self): - return 'int*' - @specialize.arg(1) def revealconst(self, T): if T is llmemory.Address: @@ -94,26 +83,83 @@ assert 0, "XXX not implemented" -class Label(GenLabel): +class Block(GenLabel): + def writecode(self, lines): + raise NotImplementedError - def __init__(self): - self.label = 'L' + str(count.n_labels) - count.n_labels += 1 - def operand(self): - return self.type() + ' %' + self.label - - def operand2(self): - return self.label + ':' - - def type(self): - return 'label' +class BasicBlock(Block): + """An llvm basic block. + The source text is stored in the 'asm' list of lines. + The phinodes dict is updated by branches and is eventually + turned into 'phi' instructions by the writecode() method. + """ + def __init__(self, rgenop, label, inputargtypes): + self.rgenop = rgenop + self.label = label + self.inputargs = [Var(type) for type in inputargtypes] + self.phinodes = {} # dict {source block: [source vars]} + self.asm = [] + rgenop.blocklist.append(self) + + def getinputargtypes(self): + return [var.type for var in self.inputargs] + + def add_incoming_link(self, sourceblock, sourcevars): + # check the types for debugging + sourcevartypes = [var.type for var in sourcevars] + targetvartypes = [var.type for var in self.inputargs] + assert sourcevartypes == targetvartypes + + # Check if the source block jumps to 'self' from multiple + # positions: in this case we need an intermediate block... + if sourceblock in self.phinodes: + tmplabel = count.newlabel() + tmpblock = BasicBlock(self.rgenop, tmplabel, targetvartypes) + tmpblock.add_incoming_link(sourceblock, sourcevars) + sourceblock = tmpblock + sourcevars = tmpblock.inputargs + + # Add this source for the phi nodes + self.phinodes[sourceblock] = list(sourcevars) + + def writecode(self, lines): + lines.append(self.label + ':') + for i in range(len(self.inputargs)): + targetvar = self.inputargs[i] + mergelist = [] + for sourceblock, sourcevars in self.phinodes.iteritems(): + mergelist.append("[%s,%%%s]" % (sourcevars[i].operand2(), + sourceblock.label)) + lines.append(' %s=phi %s %s' % (targetvar.operand2(), + targetvar.type, + ', '.join(mergelist))) + lines.extend(self.asm) -class EntryLabel(Label): +class PrologueBlock(Block): + label = 'LP' - def __init(self): - self.label = 'L_' #Block-label for alloca's. The label is never put in the source! + def __init__(self, sigtoken, name): + self.name = name + self.sigtoken = sigtoken + argtypes, restype = sigtoken + self.inputargs = [Var(type) for type in argtypes] + # self.startblocklabel set by newgraph() + + def writecode(self, lines): + argtypes, restype = self.sigtoken + lines.append('%s %%%s(%s){' % ( + restype, + self.name, + ','.join([v.operand() for v in self.inputargs]))) + lines.append(self.label + ':') + lines.append(' br label %%%s' % (self.startblocklabel,)) + + +class EpilogueBlock(Block): + def writecode(self, lines): + lines.append('}') class FlexSwitch(CodeGenSwitch): @@ -197,116 +243,44 @@ class Builder(object): #changed baseclass from (GenBuilder) for better error messages - def __init__(self, rgenop, asm, prev_block_closed=False): - self.label = EntryLabel() - log('%s Builder.__init__' % self.label.operand2()) + def __init__(self, rgenop, coming_from): self.rgenop = rgenop - self.asm = asm #list of llvm assembly source code lines - self.prev_block_closed = prev_block_closed #XXX might be a problem with empty blocks - - # ---------------------------------------------------------------- - # The public Builder interface + self.nextlabel = count.newlabel() # the label of the next block + self.block = coming_from # the old block that jumped here - def end(self): - log('%s Builder.end' % self.label.operand2()) - self.rgenop.asms.append(['}']) - #log(self.rgenop.asms) - asm_string = '' - for asm in self.rgenop.asms: - asm_string += '\n'.join(asm) + '\n' - self.rgenop.asms = None #XXX or [] ? - log(asm_string) - llvmjit.parse(asm_string) - llvmjit.transform(3) #optimize module (should be on functions actually) - function = llvmjit.getNamedFunction(self.rgenop.name) - entrypoint = llvmjit.getPointerToFunctionAsInt(function) #how to cast a ctypes ptr to int? - self.rgenop.funcname[entrypoint] = self.rgenop.funcname[self.rgenop.gv_entrypoint.value] - self.rgenop.gv_entrypoint.value = entrypoint - - def _write_prologue(self, sigtoken): - numargs = sigtoken # for now - inputargs_gv = [Var() for i in range(numargs)] - self.asm.append('int %%%s(%s){' % ( - self.rgenop.name, ','.join([v.operand() for v in inputargs_gv]))) - - inputargs_gv_ = [] - for v in inputargs_gv: - v_ = VarAddr(v, self.asm) - self.asm.append(' store %s,%s %s' % (v.operand(), v_.type(), v_.operand2())) - inputargs_gv_.append(v_) - - #self.asm.append(self.label.operand2()) - #note: alloca's should be appended to self.rgenop.asms[0] - self.asm = self.rgenop.open_asm() #note: previous self.asm already appended to self.asms - return inputargs_gv_ #XXX make this inputargs_gv_ + def _fork(self): + targetbuilder = Builder(self.rgenop, coming_from=self.block) + log('%s Builder._fork => %s' % (self.block.label, targetbuilder.nextlabel)) + return targetbuilder def _close(self): - log('%s Builder._close' % self.label.operand2()) - #self.rgenop.close_asm(self.asm) - self.asm = None - self.prev_block_closed = True - #self.mc.done() - #self.rgenop.close_mc(self.mc) - #self.mc = None + self.block = None - def _fork(self): - log('%s Builder._fork' % self.label.operand2()) - self.prev_block_closed = True - targetbuilder = self.rgenop.openbuilder(False) - targetbuilder.asm.append(targetbuilder.label.operand2()) #another HACK - return targetbuilder + def end(self): + self.rgenop.end() # XXX Hack to be removed! + + # ---------------------------------------------------------------- + # The public Builder interface @specialize.arg(1) def genop1(self, opname, gv_arg): - #log('%s Builder.genop1' % self.label.operand2()) + #log('%s Builder.genop1' % self.block.label) genmethod = getattr(self, 'op_' + opname) return genmethod(gv_arg) @specialize.arg(1) def genop2(self, opname, gv_arg1, gv_arg2): - #log('%s Builder.genop2' % self.label.operand2()) + #log('%s Builder.genop2' % self.block.label) genmethod = getattr(self, 'op_' + opname) return genmethod(gv_arg1, gv_arg2) - def _rgenop2_generic(self, llvm_opcode, gv_arg1, gv_arg2): + def _rgenop2_generic(self, llvm_opcode, gv_arg1, gv_arg2, restype='int'): log('%s Builder._rgenop2_generic %s %s,%s' % ( - self.label.operand2(), llvm_opcode, gv_arg1.operand(), gv_arg2.operand2())) - - #XXX can't this be shorter? - if gv_arg1.is_const or isinstance(gv_arg1, VarAddr): - gv_arg1_ = gv_arg1 - else: - gv_arg1_ = VarAddr(gv_arg1, self.rgenop.asms[0]) - if isinstance(gv_arg1_, VarAddr): - gv_arg1_tmp = Var() - self.asm.append(' %s=load %s' % (gv_arg1_tmp.operand2(), gv_arg1_.operand())) - else: - gv_arg1_tmp = gv_arg1_ - - if gv_arg2.is_const or isinstance(gv_arg2, VarAddr): - gv_arg2_ = gv_arg2 - else: - gv_arg2_ = VarAddr(gv_arg2, self.rgenop.asms[0]) - if isinstance(gv_arg2_, VarAddr): - gv_arg2_tmp = Var() - self.asm.append(' %s=load %s' % (gv_arg2_tmp.operand2(), gv_arg2_.operand())) - else: - gv_arg2_tmp = gv_arg2_ - - gv_result = Var() + self.block.label, llvm_opcode, gv_arg1.operand(), gv_arg2.operand2())) + gv_result = Var(restype) self.asm.append(' %s=%s %s,%s' % ( - gv_result.operand2(), llvm_opcode, gv_arg1_tmp.operand(), gv_arg2_tmp.operand2())) - - if llvm_opcode[:3] == 'set': #HACK - #XXX We assume there will always be a jump_if_true/false right after an op_int_eq/etc. - # Because we don't yet keep track of non-ints it will be difficult to do the - # right thing in jump_if_true/false. So this is a hack we want to fix later! - return gv_result - - gv_result_ = VarAddr(gv_result, self.rgenop.asms[0]) - self.asm.append(' store %s,%s' % (gv_result.operand(), gv_result_.operand())) - - return gv_result_ + gv_result.operand2(), llvm_opcode, gv_arg1.operand(), gv_arg2.operand2())) + return gv_result def op_int_add(self, gv_x, gv_y): return self._rgenop2_generic('add' , gv_x, gv_y) def op_int_sub(self, gv_x, gv_y): return self._rgenop2_generic('sub' , gv_x, gv_y) @@ -316,12 +290,12 @@ def op_int_and(self, gv_x, gv_y): return self._rgenop2_generic('and' , gv_x, gv_y) def op_int_or(self, gv_x, gv_y): return self._rgenop2_generic('or' , gv_x, gv_y) def op_int_xor(self, gv_x, gv_y): return self._rgenop2_generic('xor' , gv_x, gv_y) - def op_int_lt(self, gv_x, gv_y): return self._rgenop2_generic('setlt', gv_x, gv_y) - def op_int_le(self, gv_x, gv_y): return self._rgenop2_generic('setle', gv_x, gv_y) - def op_int_eq(self, gv_x, gv_y): return self._rgenop2_generic('seteq', gv_x, gv_y) - def op_int_ne(self, gv_x, gv_y): return self._rgenop2_generic('setne', gv_x, gv_y) - def op_int_gt(self, gv_x, gv_y): return self._rgenop2_generic('setgt', gv_x, gv_y) - def op_int_ge(self, gv_x, gv_y): return self._rgenop2_generic('setge', gv_x, gv_y) + def op_int_lt(self, gv_x, gv_y): return self._rgenop2_generic('setlt', gv_x, gv_y, 'bool') + def op_int_le(self, gv_x, gv_y): return self._rgenop2_generic('setle', gv_x, gv_y, 'bool') + def op_int_eq(self, gv_x, gv_y): return self._rgenop2_generic('seteq', gv_x, gv_y, 'bool') + def op_int_ne(self, gv_x, gv_y): return self._rgenop2_generic('setne', gv_x, gv_y, 'bool') + def op_int_gt(self, gv_x, gv_y): return self._rgenop2_generic('setgt', gv_x, gv_y, 'bool') + def op_int_ge(self, gv_x, gv_y): return self._rgenop2_generic('setge', gv_x, gv_y, 'bool') #def op_int_neg(self, gv_x): #def op_int_abs(self, gv_x): @@ -332,82 +306,58 @@ #def op_cast_bool_to_int(self, gv_x): def enter_next_block(self, kinds, args_gv): - label = Label() - log('%s Builder.enter_next_block (was %s), prev_block_closed=%s, %s' % ( - label.operand2(), self.label.operand2(), str(self.prev_block_closed), - [v.operand() for v in args_gv])) - self.label = label - if not self.prev_block_closed: #there are not always explicit branches to blocks - self.asm.append(' br ' + self.label.operand() + ' ;fixup') - self.asm.append(self.label.operand2()) - #XXX These phi nodes seems to get really messy especially with the 'fixup' branches. - #XXX Perhaps using alloca's and omitting the phi nodes does make some sense. - self.asm.append(' ;phi %s' % [v.operand() for v in args_gv]) - self.prev_block_closed = False #easiest, but might be a problem with empty blocks - return self.label - #arg_positions = [] - #seen = {} - #for i in range(len(args_gv)): - # gv = args_gv[i] - # # turn constants into variables; also make copies of vars that - # # are duplicate in args_gv - # if not isinstance(gv, Var) or gv.stackpos in seen: - # gv = args_gv[i] = self.returnvar(gv.operand(self)) - # # remember the var's position in the stack - # arg_positions.append(gv.stackpos) - # seen[gv.stackpos] = None - #return Label(self.mc.tell(), arg_positions, self.stackdepth) + # if nextlabel is None, it means that we are currently + # generating a block; in this case we need to put a br + # to go to the next block + if self.nextlabel is None: + self.nextlabel = count.newlabel() + self.asm.append(' br label %%%s' % (self.nextlabel,)) + coming_from = self.block + log('%s Builder leave block %s' % ( + coming_from.label, [v.operand() for v in args_gv])) + + # prepare the next block + nextblock = BasicBlock(self.rgenop, self.nextlabel, kinds) + log('%s Builder enter block %s' % ( + nextblock.label, [v.operand() for v in nextblock.inputargs])) + self.block = nextblock + self.asm = nextblock.asm + self.nextlabel = None + + # link the two blocks together and update args_gv + nextblock.add_incoming_link(coming_from, args_gv) + for i in range(len(args_gv)): + args_gv[i] = nextblock.inputargs[i] + + return self.block def jump_if_false(self, gv_condition): - log('%s Builder.jump_if_false %s' % (self.label.operand2(), gv_condition.operand())) + log('%s Builder.jump_if_false %s' % (self.block.label, gv_condition.operand())) targetbuilder = self._fork() - - #XXX the next couple of lines are incorrect! Should we make this a two-pass algorithm? - no_branch = Label() #XXX should be this Builder's next 'enter_next_block' label - count.n_labels -= 1 #HACK HACK HACK - #XXX will need to keep type of Vars to get rid of the hardcoded 'bool' in the next line - targetlabel = targetbuilder.label - - self.asm.append(' br bool %s,%s,%s' % ( - gv_condition.operand2(), no_branch.operand(), targetlabel.operand())) - #XXX self.asm.append(no_branch.operand2()) - #self.mc.CMP(gv_condition.operand(self), imm8(0)) - #self.mc.JNE(rel32(targetbuilder.mc.tell())) + self.nextlabel = count.newlabel() + self.asm.append(' br %s,label %%%s,label %%%s' % ( + gv_condition.operand(), self.nextlabel, targetbuilder.nextlabel)) return targetbuilder def jump_if_true(self, gv_condition): - log('%s Builder.jump_if_true %s' % (self.label.operand2(), gv_condition.operand())) + log('%s Builder.jump_if_true %s' % (self.block.label, gv_condition.operand())) targetbuilder = self._fork() - - #XXX the next couple of lines are incorrect! Should we make this a two-pass algorithm? - no_branch = Label() #XXX should be this Builder's next 'enter_next_block' label - count.n_labels -= 1 #HACK HACK HACK - #XXX will need to keep type (bool/int/float/...) of Vars - targetlabel = targetbuilder.label - - self.asm.append(' br bool %s,%s,%s' % ( - gv_condition.operand2(), targetlabel.operand(), no_branch.operand())) - #XXX self.asm.append(no_branch.operand2()) - #self.mc.CMP(gv_condition.operand(self), imm8(0)) - #self.mc.JNE(rel32(targetbuilder.mc.tell())) + self.nextlabel = count.newlabel() + self.asm.append(' br %s,label %%%s,label %%%s' % ( + gv_condition.operand(), targetbuilder.nextlabel, self.nextlabel)) return targetbuilder - def op_int_is_true(self, gv_x_): - log('%s Build.op_int_is_true %s' % (self.label.operand2(), gv_x_.operand())) - if isinstance(gv_x_, VarAddr): - gv_x = Var() - self.asm.append(' %s=load %s' % (gv_x.operand2(), gv_x_.operand())) - else: - gv_x = gv_x_ - gv_result = Var() #XXX need to mark it a 'bool' somehow - self.asm.append(' %s=trunc %s to bool' % (gv_result.operand2(), gv_x.operand())) + def op_int_is_true(self, gv_x): + log('%s Build.op_int_is_true %s' % (self.block.label, gv_x.operand())) + gv_result = Var('bool') + self.asm.append(' %s=setne %s,0' % (gv_result.operand2(), gv_x.operand())) return gv_result def genop_call(self, sigtoken, gv_fnptr, args_gv): log('%s Builder.genop_call %s,%s,%s' % ( - self.label.operand2(), sigtoken, gv_fnptr, [v.operand() for v in args_gv])) - numargs = sigtoken #for now - gv_returnvar = Var() + self.block.label, sigtoken, gv_fnptr, [v.operand() for v in args_gv])) + argtypes, restype = sigtoken + gv_returnvar = Var(restype) #XXX we probably need to call an address directly if we can't resolve the funcname self.asm.append(' %s=call %s(%s)' % ( gv_returnvar.operand2(), @@ -415,34 +365,23 @@ ','.join([v.operand() for v in args_gv]))) return gv_returnvar - def finish_and_return(self, sigtoken, gv_returnvar_): + def finish_and_return(self, sigtoken, gv_returnvar): log('%s Builder.finish_and_return %s,%s' % ( - self.label.operand2(), sigtoken, gv_returnvar_.operand())) - - if isinstance(gv_returnvar_, VarAddr): - gv_returnvar = Var() - self.asm.append(' %s=load %s' % (gv_returnvar.operand2(), gv_returnvar_.operand())) - else: - gv_returnvar = gv_returnvar_ + self.block.label, sigtoken, gv_returnvar.operand())) self.asm.append(' ret ' + gv_returnvar.operand()) - #numargs = sigtoken # for now - #initialstackdepth = numargs + 1 - #self.mc.MOV(eax, gv_returnvar.operand(self)) - #self.mc.ADD(esp, imm(WORD * (self.stackdepth - initialstackdepth))) - #self.mc.RET() self._close() def finish_and_goto(self, outputargs_gv, target): + # 'target' is a label, which for the llvm backend is a Block gv = [v.operand() for v in outputargs_gv] log('%s Builder.finish_and_goto %s,%s' % ( - self.label.operand2(), gv, target.operand())) - self.asm.append(' br %s ;%s' % (target.operand(), gv)) - #remap_stack_layout(self, outputargs_gv, target) - #self.mc.JMP(rel32(target.startaddr)) + self.block.label, gv, target.label)) + self.asm.append(' br label %%%s' % (target.label,)) + target.add_incoming_link(self.block, outputargs_gv) self._close() def flexswitch(self, gv_exitswitch): - log('%s Builder.flexswitch %s' % (self.label.operand2(), gv_exitswitch.operand())) + log('%s Builder.flexswitch %s' % (self.block.label, gv_exitswitch.operand())) self.asm.append(' ;flexswitch ' + gv_exitswitch.operand()) result = FlexSwitch(self.rgenop) result.initialize(self, gv_exitswitch) @@ -459,21 +398,29 @@ funcname = {} #HACK for looking up function names given a pre/post compilation function pointer funcused = {} #we rename functions when encountered multiple times (for test_branching_compile) - def open_asm(self): - asm = [] - self.asms.append(asm) - return asm + def end(self): + log('RLLVMGenOp.end') + self.blocklist.append(EpilogueBlock()) + asmlines = [] + for block in self.blocklist: + block.writecode(asmlines) + asmlines.append('') + asm_string = '\n'.join(asmlines) - #def close_asm(self, asm): - # self.asms.append(asm) + self.blocklist = None + log(asm_string) + llvmjit.parse(asm_string) + llvmjit.transform(3) #optimize module (should be on functions actually) + function = llvmjit.getNamedFunction(self.name) + entrypoint = llvmjit.getPointerToFunctionAsInt(function) + # XXX or directly cast the ctypes ptr to int with: + # ctypes.cast(ptr, c_void_p).value + self.funcname[entrypoint] = self.funcname[self.gv_entrypoint.value] + self.gv_entrypoint.value = entrypoint # ---------------------------------------------------------------- # the public RGenOp interface - def openbuilder(self, prev_block_closed): - #log('RLLVMGenOp.openbuilder %s' % (str(prev_block_closed)) - return Builder(self, self.open_asm(), prev_block_closed) - def newgraph(self, sigtoken, name): if name in self.funcused: self.funcused[name] += 1 @@ -482,19 +429,24 @@ self.funcused[name] = 0 log('RLLVMGenOp.newgraph %s,%s' % (sigtoken, name)) - self.asms = [] - numargs = sigtoken # for now - self.name = name - builder = self.openbuilder(False) #enables initial label - inputargs_gv = builder._write_prologue(sigtoken) + + prologueblock = PrologueBlock(sigtoken, name) + self.blocklist = [prologueblock] + builder = Builder(self, coming_from=prologueblock) + prologueblock.startblocklabel = builder.nextlabel + + argtypes, restype = sigtoken n = len(self.funcname) * 2 + 1 #+1 so we recognize these pre compilation 'pointers' - self.funcname[n] = 'int %' + name #XXX 'int' hardcoded currently as in write_prologue() + self.name = name + self.funcname[n] = '%s %%%s' % (restype, name) self.gv_entrypoint = IntConst(n) #note: updated by Builder.end() (i.e after compilation) - return builder, self.gv_entrypoint, inputargs_gv + args = list(prologueblock.inputargs) + builder.enter_next_block(argtypes, args) + return builder, self.gv_entrypoint, args @specialize.genconst(1) - def genconst(self, llvalue): #i386 version (ppc version is slightly different) - T = lltype.typeOf(llvalue) + def genconst(self, llvalue): + T = lltype.typeOf(llvalue) if T is llmemory.Address: return AddrConst(llvalue) elif isinstance(T, lltype.Primitive): @@ -511,8 +463,22 @@ @staticmethod @specialize.memo() + def kindToken(T): + # turn the type T into the llvm approximation that we'll use here + # XXX incomplete + if isinstance(T, lltype.Ptr): + return 'int*' + elif T is llmemory.Address: + return 'int*' + elif T is lltype.Bool: + return 'bool' + else: + return 'int' + + @staticmethod + @specialize.memo() def fieldToken(T, name): - return llmemory.offsetof(T, name) + return (RLLVMGenOp.kindToken(T), llmemory.offsetof(T, name)) @staticmethod @specialize.memo() @@ -522,6 +488,7 @@ @staticmethod @specialize.memo() def varsizeAllocToken(T): + XXX if isinstance(T, lltype.Array): return RI386GenOp.arrayToken(T) else: @@ -538,19 +505,17 @@ @staticmethod @specialize.memo() def arrayToken(A): + XXX return (llmemory.ArrayLengthOffset(A), llmemory.ArrayItemsOffset(A), llmemory.ItemOffset(A.OF)) @staticmethod @specialize.memo() - def kindToken(T): - return None # for now - - @staticmethod - @specialize.memo() def sigToken(FUNCTYPE): - return len(FUNCTYPE.ARGS) # for now + argtypes = [RLLVMGenOp.kindToken(T) for T in FUNCTYPE.ARGS] + restype = RLLVMGenOp.kindToken(FUNCTYPE.RESULT) + return (argtypes, restype) @staticmethod def erasedType(T): Modified: pypy/dist/pypy/jit/codegen/llvm/test/test_rgenop.py ============================================================================== --- pypy/dist/pypy/jit/codegen/llvm/test/test_rgenop.py (original) +++ pypy/dist/pypy/jit/codegen/llvm/test/test_rgenop.py Sat Dec 9 17:18:11 2006 @@ -14,17 +14,8 @@ def skip(self): py.test.skip('WIP') - test_goto_direct = skip - test_goto_compile = skip - - test_if_direct = skip - test_if_compile = skip - test_switch_direct = skip test_switch_compile = skip test_large_switch_direct = skip test_large_switch_compile = skip - - test_fact_direct = skip - test_fact_compile = skip From arigo at codespeak.net Sat Dec 9 18:20:09 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 9 Dec 2006 18:20:09 +0100 (CET) Subject: [pypy-svn] r35539 - in pypy/dist/pypy: . annotation annotation/test config jit/codegen/ppc jit/codegen/ppc/test objspace objspace/flow objspace/flow/test objspace/std rlib rpython rpython/lltypesystem rpython/ootypesystem rpython/ootypesystem/test rpython/test tool translator translator/c translator/goal translator/tool Message-ID: <20061209172009.1CC1610036@code0.codespeak.net> Author: arigo Date: Sat Dec 9 18:20:08 2006 New Revision: 35539 Added: pypy/dist/pypy/annotation/binaryop.py - copied unchanged from r35513, pypy/dist/pypy/annotation/binaryop.py pypy/dist/pypy/annotation/description.py - copied unchanged from r35513, pypy/dist/pypy/annotation/description.py pypy/dist/pypy/annotation/policy.py - copied unchanged from r35513, pypy/dist/pypy/annotation/policy.py pypy/dist/pypy/annotation/test/test_annrpython.py - copied unchanged from r35513, pypy/dist/pypy/annotation/test/test_annrpython.py pypy/dist/pypy/config/config.py - copied unchanged from r35513, pypy/dist/pypy/config/config.py pypy/dist/pypy/config/translationoption.py - copied unchanged from r35513, pypy/dist/pypy/config/translationoption.py pypy/dist/pypy/conftest.py - copied unchanged from r35513, pypy/dist/pypy/conftest.py pypy/dist/pypy/jit/codegen/ppc/rgenop.py - copied unchanged from r35513, pypy/dist/pypy/jit/codegen/ppc/rgenop.py pypy/dist/pypy/jit/codegen/ppc/test/test_emit_moves.py - copied unchanged from r35513, pypy/dist/pypy/jit/codegen/ppc/test/test_emit_moves.py pypy/dist/pypy/jit/codegen/ppc/test/test_genc_ts.py - copied unchanged from r35513, pypy/dist/pypy/jit/codegen/ppc/test/test_genc_ts.py pypy/dist/pypy/objspace/flow/objspace.py - copied unchanged from r35513, pypy/dist/pypy/objspace/flow/objspace.py pypy/dist/pypy/objspace/flow/specialcase.py - copied unchanged from r35513, pypy/dist/pypy/objspace/flow/specialcase.py pypy/dist/pypy/objspace/flow/test/test_objspace.py - copied unchanged from r35513, pypy/dist/pypy/objspace/flow/test/test_objspace.py pypy/dist/pypy/objspace/flow/test/test_unroll.py - copied unchanged from r35513, pypy/dist/pypy/objspace/flow/test/test_unroll.py pypy/dist/pypy/objspace/logic.py - copied unchanged from r35513, pypy/dist/pypy/objspace/logic.py pypy/dist/pypy/objspace/std/complexobject.py - copied unchanged from r35513, pypy/dist/pypy/objspace/std/complexobject.py pypy/dist/pypy/rlib/rarithmetic.py - copied unchanged from r35513, pypy/dist/pypy/rlib/rarithmetic.py pypy/dist/pypy/rlib/ros.py - copied unchanged from r35513, pypy/dist/pypy/rlib/ros.py pypy/dist/pypy/rlib/unroll.py - copied unchanged from r35513, pypy/dist/pypy/rlib/unroll.py pypy/dist/pypy/rpython/annlowlevel.py - copied unchanged from r35513, pypy/dist/pypy/rpython/annlowlevel.py pypy/dist/pypy/rpython/extfunctable.py - copied unchanged from r35513, pypy/dist/pypy/rpython/extfunctable.py pypy/dist/pypy/rpython/lltypesystem/rlist.py - copied unchanged from r35513, pypy/dist/pypy/rpython/lltypesystem/rlist.py pypy/dist/pypy/rpython/lltypesystem/rpbc.py - copied unchanged from r35513, pypy/dist/pypy/rpython/lltypesystem/rpbc.py pypy/dist/pypy/rpython/lltypesystem/rstr.py - copied unchanged from r35513, pypy/dist/pypy/rpython/lltypesystem/rstr.py pypy/dist/pypy/rpython/lltypesystem/rtuple.py - copied unchanged from r35513, pypy/dist/pypy/rpython/lltypesystem/rtuple.py pypy/dist/pypy/rpython/ootypesystem/ll_str.py - copied unchanged from r35513, pypy/dist/pypy/rpython/ootypesystem/ll_str.py pypy/dist/pypy/rpython/ootypesystem/ooregistry.py - copied unchanged from r35513, pypy/dist/pypy/rpython/ootypesystem/ooregistry.py pypy/dist/pypy/rpython/ootypesystem/rbuiltin.py - copied unchanged from r35513, pypy/dist/pypy/rpython/ootypesystem/rbuiltin.py pypy/dist/pypy/rpython/ootypesystem/rclass.py - copied unchanged from r35513, pypy/dist/pypy/rpython/ootypesystem/rclass.py pypy/dist/pypy/rpython/ootypesystem/rlist.py - copied unchanged from r35513, pypy/dist/pypy/rpython/ootypesystem/rlist.py pypy/dist/pypy/rpython/ootypesystem/rstr.py - copied unchanged from r35513, pypy/dist/pypy/rpython/ootypesystem/rstr.py pypy/dist/pypy/rpython/ootypesystem/rtuple.py - copied unchanged from r35513, pypy/dist/pypy/rpython/ootypesystem/rtuple.py pypy/dist/pypy/rpython/ootypesystem/test/test_ooregistry.py - copied unchanged from r35513, pypy/dist/pypy/rpython/ootypesystem/test/test_ooregistry.py pypy/dist/pypy/rpython/ootypesystem/test/test_oortype.py - copied unchanged from r35513, pypy/dist/pypy/rpython/ootypesystem/test/test_oortype.py pypy/dist/pypy/rpython/raddress.py - copied unchanged from r35513, pypy/dist/pypy/rpython/raddress.py pypy/dist/pypy/rpython/rexternalobj.py - copied unchanged from r35513, pypy/dist/pypy/rpython/rexternalobj.py pypy/dist/pypy/rpython/rlist.py - copied unchanged from r35513, pypy/dist/pypy/rpython/rlist.py pypy/dist/pypy/rpython/rmodel.py - copied unchanged from r35513, pypy/dist/pypy/rpython/rmodel.py pypy/dist/pypy/rpython/robject.py - copied unchanged from r35513, pypy/dist/pypy/rpython/robject.py pypy/dist/pypy/rpython/rpbc.py - copied unchanged from r35513, pypy/dist/pypy/rpython/rpbc.py pypy/dist/pypy/rpython/rptr.py - copied unchanged from r35513, pypy/dist/pypy/rpython/rptr.py pypy/dist/pypy/rpython/rtuple.py - copied unchanged from r35513, pypy/dist/pypy/rpython/rtuple.py pypy/dist/pypy/rpython/test/test_exception.py - copied unchanged from r35513, pypy/dist/pypy/rpython/test/test_exception.py pypy/dist/pypy/rpython/test/test_llinterp.py - copied unchanged from r35513, pypy/dist/pypy/rpython/test/test_llinterp.py pypy/dist/pypy/rpython/test/test_rlist.py - copied unchanged from r35513, pypy/dist/pypy/rpython/test/test_rlist.py pypy/dist/pypy/rpython/test/test_rpbc.py - copied unchanged from r35513, pypy/dist/pypy/rpython/test/test_rpbc.py pypy/dist/pypy/rpython/test/test_rptr.py - copied unchanged from r35513, pypy/dist/pypy/rpython/test/test_rptr.py pypy/dist/pypy/rpython/test/test_rstr.py - copied unchanged from r35513, pypy/dist/pypy/rpython/test/test_rstr.py pypy/dist/pypy/rpython/test/test_rtuple.py - copied unchanged from r35513, pypy/dist/pypy/rpython/test/test_rtuple.py pypy/dist/pypy/tool/option.py - copied unchanged from r35513, pypy/dist/pypy/tool/option.py pypy/dist/pypy/translator/c/exceptiontransform.py - copied unchanged from r35513, pypy/dist/pypy/translator/c/exceptiontransform.py pypy/dist/pypy/translator/c/extfunc.py - copied unchanged from r35513, pypy/dist/pypy/translator/c/extfunc.py pypy/dist/pypy/translator/c/genc.py - copied unchanged from r35513, pypy/dist/pypy/translator/c/genc.py pypy/dist/pypy/translator/c/primitive.py - copied unchanged from r35513, pypy/dist/pypy/translator/c/primitive.py pypy/dist/pypy/translator/c/support.py - copied unchanged from r35513, pypy/dist/pypy/translator/c/support.py pypy/dist/pypy/translator/c/wrapper.py - copied unchanged from r35513, pypy/dist/pypy/translator/c/wrapper.py pypy/dist/pypy/translator/driver.py - copied unchanged from r35513, pypy/dist/pypy/translator/driver.py pypy/dist/pypy/translator/geninterplevel.py - copied unchanged from r35513, pypy/dist/pypy/translator/geninterplevel.py pypy/dist/pypy/translator/goal/ann_override.py - copied unchanged from r35513, pypy/dist/pypy/translator/goal/ann_override.py pypy/dist/pypy/translator/goal/app_main.py - copied unchanged from r35513, pypy/dist/pypy/translator/goal/app_main.py pypy/dist/pypy/translator/goal/bench-cronjob.py - copied unchanged from r35513, pypy/dist/pypy/translator/goal/bench-cronjob.py pypy/dist/pypy/translator/goal/bench-custom.py - copied unchanged from r35513, pypy/dist/pypy/translator/goal/bench-custom.py pypy/dist/pypy/translator/goal/bench-unix.py - copied unchanged from r35513, pypy/dist/pypy/translator/goal/bench-unix.py pypy/dist/pypy/translator/goal/targetmultiplespaces.py - copied unchanged from r35513, pypy/dist/pypy/translator/goal/targetmultiplespaces.py pypy/dist/pypy/translator/interactive.py - copied unchanged from r35513, pypy/dist/pypy/translator/interactive.py pypy/dist/pypy/translator/tool/graphpage.py - copied unchanged from r35513, pypy/dist/pypy/translator/tool/graphpage.py pypy/dist/pypy/translator/tool/raymond.py - copied unchanged from r35513, pypy/dist/pypy/translator/tool/raymond.py pypy/dist/pypy/translator/translator.py - copied unchanged from r35513, pypy/dist/pypy/translator/translator.py Log: Trying to fix the history of some files left broken by the merge. This won't restore the history of directories, though, but it's better than nothing... From arigo at codespeak.net Sat Dec 9 18:21:36 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 9 Dec 2006 18:21:36 +0100 (CET) Subject: [pypy-svn] r35540 - pypy/dist/pypy/jit/codegen/ppc/test Message-ID: <20061209172136.38F711006F@code0.codespeak.net> Author: arigo Date: Sat Dec 9 18:21:35 2006 New Revision: 35540 Modified: pypy/dist/pypy/jit/codegen/ppc/test/test_emit_moves.py (props changed) pypy/dist/pypy/jit/codegen/ppc/test/test_genc_ts.py (props changed) Log: fixeol From antocuni at codespeak.net Sun Dec 10 12:01:15 2006 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Sun, 10 Dec 2006 12:01:15 +0100 (CET) Subject: [pypy-svn] r35545 - pypy/dist/pypy/translator Message-ID: <20061210110115.EB9581006E@code0.codespeak.net> Author: antocuni Date: Sun Dec 10 12:01:14 2006 New Revision: 35545 Modified: pypy/dist/pypy/translator/driver.py Log: Don't change the cwd when executing pypy.net. Modified: pypy/dist/pypy/translator/driver.py ============================================================================== --- pypy/dist/pypy/translator/driver.py (original) +++ pypy/dist/pypy/translator/driver.py Sun Dec 10 12:01:14 2006 @@ -601,8 +601,7 @@ newexename = './' + newexename f = file(newexename, 'w') f.write("""#!/bin/bash -cd `dirname $0` # XXX doesn't work if it's placed in PATH -mono "%s" "$@" +mono "$(dirname $0)/%s" "$@" # XXX doesn't work if it's placed in PATH """ % main_exe_name) f.close() os.chmod(newexename, 0755) From arigo at codespeak.net Sun Dec 10 14:19:58 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 10 Dec 2006 14:19:58 +0100 (CET) Subject: [pypy-svn] r35546 - in pypy/dist/pypy/doc: . discussion Message-ID: <20061210131958.70C9B1006E@code0.codespeak.net> Author: arigo Date: Sun Dec 10 14:19:55 2006 New Revision: 35546 Removed: pypy/dist/pypy/doc/discussion/draft-jit-ideas.txt Modified: pypy/dist/pypy/doc/draft-jit-outline.txt pypy/dist/pypy/doc/jit.txt Log: Update the outline, redirect from the other jit-related document, kill the oldest out-of-date document. Modified: pypy/dist/pypy/doc/draft-jit-outline.txt ============================================================================== --- pypy/dist/pypy/doc/draft-jit-outline.txt (original) +++ pypy/dist/pypy/doc/draft-jit-outline.txt Sun Dec 10 14:19:55 2006 @@ -13,12 +13,25 @@ Hint annotator and hint(concrete=True)... +calls... + +green propagation at fixpoint... + +deepfreeze... + +blue containers... + Timeshifting: transforming interpreter into compilers ====================================================== intro and basics +Transform vs hrtyping +----------------------- + +... + Split and Merges -------------------- @@ -32,6 +45,11 @@ Virtual Containers -------------------- +...vstructs, vlist, vdict... + +Exceptions +------------ + ... Promotion and global merges @@ -39,17 +57,21 @@ ... -partial data +Partial data ------------- ... - Portals ---------------------- ... +Scaling to PyPy +---------------------- + +... + Backends ==================== Modified: pypy/dist/pypy/doc/jit.txt ============================================================================== --- pypy/dist/pypy/doc/jit.txt (original) +++ pypy/dist/pypy/doc/jit.txt Sun Dec 10 14:19:55 2006 @@ -6,6 +6,10 @@ Warning: These are just a few notes quickly thrown together, to be clarified and expanded. +For now we are working on the parallel document `draft-jit-outline`_. + +.. _`draft-jit-outline`: draft-jit-outline.html + Draft ========================= From arigo at codespeak.net Sun Dec 10 14:43:06 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 10 Dec 2006 14:43:06 +0100 (CET) Subject: [pypy-svn] r35547 - pypy/dist/pypy/module/__builtin__/test Message-ID: <20061210134306.7B31D10063@code0.codespeak.net> Author: arigo Date: Sun Dec 10 14:43:04 2006 New Revision: 35547 Modified: pypy/dist/pypy/module/__builtin__/test/test_import.py Log: Put the new directory in front of sys.path, not at the end. I tend to have x.py files around. 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 Sun Dec 10 14:43:04 2006 @@ -82,15 +82,16 @@ return space.appexec([space.wrap(dn)], """ (dn): import sys - sys.path.append(dn) - return sys.modules.copy() + path = list(sys.path) + sys.path.insert(0, dn) + return path, sys.modules.copy() """) def _teardown(space, w_saved_modules): space.appexec([w_saved_modules], """ - (saved_modules): + ((saved_path, saved_modules)): import sys - sys.path.pop() + sys.path[:] = saved_path sys.modules.clear() sys.modules.update(saved_modules) """) From ericvrp at codespeak.net Sun Dec 10 14:48:48 2006 From: ericvrp at codespeak.net (ericvrp at codespeak.net) Date: Sun, 10 Dec 2006 14:48:48 +0100 (CET) Subject: [pypy-svn] r35548 - pypy/dist/pypy/jit/codegen/i386/test Message-ID: <20061210134848.AB0F310070@code0.codespeak.net> Author: ericvrp Date: Sun Dec 10 14:48:47 2006 New Revision: 35548 Modified: pypy/dist/pypy/jit/codegen/i386/test/test_operation.py Log: tiny refactoring to enable sharing operation i386 tests with the llvm jit backend Modified: pypy/dist/pypy/jit/codegen/i386/test/test_operation.py ============================================================================== --- pypy/dist/pypy/jit/codegen/i386/test/test_operation.py (original) +++ pypy/dist/pypy/jit/codegen/i386/test/test_operation.py Sun Dec 10 14:48:47 2006 @@ -43,13 +43,14 @@ class TestBasic: + RGenOp = RGenOpPacked def rgen(self, ll_function, argtypes): t = TranslationContext() t.buildannotator().build_types(ll_function, argtypes) t.buildrtyper().specialize() graph = graphof(t, ll_function) - rgenop = RGenOpPacked() + rgenop = self.RGenOp() self.rgenop = rgenop # keep this alive! gv_generated = graph2rgenop.compile_graph(rgenop, graph) ctypestypes = [c_int] * len(argtypes) # for now From ericvrp at codespeak.net Sun Dec 10 15:10:20 2006 From: ericvrp at codespeak.net (ericvrp at codespeak.net) Date: Sun, 10 Dec 2006 15:10:20 +0100 (CET) Subject: [pypy-svn] r35549 - pypy/dist/pypy/jit/codegen/llvm/test Message-ID: <20061210141020.059AC10071@code0.codespeak.net> Author: ericvrp Date: Sun Dec 10 15:10:17 2006 New Revision: 35549 Added: pypy/dist/pypy/jit/codegen/llvm/test/test_genc_portal.py (contents, props changed) pypy/dist/pypy/jit/codegen/llvm/test/test_genc_promotion.py (contents, props changed) pypy/dist/pypy/jit/codegen/llvm/test/test_genc_tlr.py - copied, changed from r35548, pypy/dist/pypy/jit/codegen/llvm/test/test_genc_tl.py pypy/dist/pypy/jit/codegen/llvm/test/test_genc_vlist.py - copied, changed from r35548, pypy/dist/pypy/jit/codegen/i386/test/test_genc_vlist.py pypy/dist/pypy/jit/codegen/llvm/test/test_operation.py (contents, props changed) Modified: pypy/dist/pypy/jit/codegen/llvm/test/test_genc_tl.py pypy/dist/pypy/jit/codegen/llvm/test/test_genc_ts.py Log: Added (shared) tests that should eventually pass on the llvm jit backend too. Added: pypy/dist/pypy/jit/codegen/llvm/test/test_genc_portal.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/jit/codegen/llvm/test/test_genc_portal.py Sun Dec 10 15:10:17 2006 @@ -0,0 +1,17 @@ +import py +from pypy.jit.codegen.i386.test.test_genc_portal import I386PortalTestMixin +from pypy.jit.timeshifter.test import test_portal +from pypy.jit.codegen.llvm.rgenop import RLLVMGenOp + +py.test.skip("WIP") + +class LLVMPortalTestMixin(I386PortalTestMixin): + RGenOp = RLLVMGenOp + +class TestPortal(LLVMPortalTestMixin, + test_portal.TestPortal): + + # for the individual tests see + # ====> ../../../timeshifter/test/test_portal.py + pass + Added: pypy/dist/pypy/jit/codegen/llvm/test/test_genc_promotion.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/jit/codegen/llvm/test/test_genc_promotion.py Sun Dec 10 15:10:17 2006 @@ -0,0 +1,12 @@ +import py +from pypy.jit.timeshifter.test import test_promotion +from pypy.jit.codegen.llvm.test.test_genc_ts import LLVMTimeshiftingTestMixin + +py.test.skip("WIP") + +class TestPromotion(LLVMTimeshiftingTestMixin, + test_promotion.TestPromotion): + + # for the individual tests see + # ====> ../../../timeshifter/test/test_promotion.py + pass Modified: pypy/dist/pypy/jit/codegen/llvm/test/test_genc_tl.py ============================================================================== --- pypy/dist/pypy/jit/codegen/llvm/test/test_genc_tl.py (original) +++ pypy/dist/pypy/jit/codegen/llvm/test/test_genc_tl.py Sun Dec 10 15:10:17 2006 @@ -5,7 +5,7 @@ py.test.skip("WIP") -class TestTLR(LLVMTimeshiftingTestMixin, +class TestTL(LLVMTimeshiftingTestMixin, test_tl.TestTL): # for the individual tests see 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 Sun Dec 10 15:10:17 2006 @@ -4,11 +4,11 @@ from pypy.jit.codegen.llvm.rgenop import RLLVMGenOp -py.test.skip("WIP") - class LLVMTimeshiftingTestMixin(I386TimeshiftingTestMixin): RGenOp = RLLVMGenOp +py.test.skip("WIP") + class TestTimeshiftLLVM(LLVMTimeshiftingTestMixin, test_timeshift.TestTimeshift): Added: pypy/dist/pypy/jit/codegen/llvm/test/test_operation.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/jit/codegen/llvm/test/test_operation.py Sun Dec 10 15:10:17 2006 @@ -0,0 +1,14 @@ +import py +from pypy.jit.codegen.i386.test.test_operation import TestBasic +from pypy.jit.codegen.llvm.rgenop import RLLVMGenOp + +py.test.skip("WIP") + +class LLVMTestBasic(TestBasic): + RGenOp = RLLVMGenOp + + # for the individual tests see + # ====> ../../../i386/test/test_operation.py + + pass + From arigo at codespeak.net Sun Dec 10 15:23:13 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 10 Dec 2006 15:23:13 +0100 (CET) Subject: [pypy-svn] r35550 - pypy/dist/pypy/module/_weakref/test Message-ID: <20061210142313.6A6AE10063@code0.codespeak.net> Author: arigo Date: Sun Dec 10 15:23:10 2006 New Revision: 35550 Modified: pypy/dist/pypy/module/_weakref/test/test_weakref.py Log: Weakrefs without support from the underlying GC don't really work, it seems. Here is an example that breaks on top of the framework GC when run as 'py.test -A'. The problem is that we don't know if the lifeline is deleted at the same time as the object. In the present case, because of its __del__ the object is deleted one collection earlier than the lifeline. Modified: pypy/dist/pypy/module/_weakref/test/test_weakref.py ============================================================================== --- pypy/dist/pypy/module/_weakref/test/test_weakref.py (original) +++ pypy/dist/pypy/module/_weakref/test/test_weakref.py Sun Dec 10 15:23:10 2006 @@ -252,6 +252,23 @@ # leads to the fact that the __del__ of _weakref.ref is not called. assert _weakref.getweakrefs(a)[0]() is a + def test_buggy_case(self): + import gc, weakref + gone = [] + class A(object): + def __del__(self): + gone.append(True) + a = A() + w = weakref.ref(a) + del a + tries = 5 + for i in range(5): + if not gone: + gc.collect() + if gone: + a1 = w() + assert a1 is None + class AppTestProxy(object): def setup_class(cls): From arigo at codespeak.net Sun Dec 10 15:27:19 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 10 Dec 2006 15:27:19 +0100 (CET) Subject: [pypy-svn] r35551 - pypy/dist/pypy/objspace/test Message-ID: <20061210142719.92FC910071@code0.codespeak.net> Author: arigo Date: Sun Dec 10 15:27:16 2006 New Revision: 35551 Modified: pypy/dist/pypy/objspace/test/test_logicobjspace.py Log: We added an extra recursion level in the interpreter main loop, which makes this test exhaust the CPython stack a bit earlier than before. Modified: pypy/dist/pypy/objspace/test/test_logicobjspace.py ============================================================================== --- pypy/dist/pypy/objspace/test/test_logicobjspace.py (original) +++ pypy/dist/pypy/objspace/test/test_logicobjspace.py Sun Dec 10 15:27:16 2006 @@ -476,9 +476,9 @@ X = newvar() F = future(fib, X) - # values > 11 triggers exhaustion of the cpython stack - unify(11, X) - assert F == 144 + # values > 10 triggers exhaustion of the cpython stack + unify(10, X) + assert F == 89 def test_stacklet(self): From arigo at codespeak.net Sun Dec 10 15:34:44 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 10 Dec 2006 15:34:44 +0100 (CET) Subject: [pypy-svn] r35552 - pypy/dist/pypy/tool Message-ID: <20061210143444.1F5A410071@code0.codespeak.net> Author: arigo Date: Sun Dec 10 15:34:42 2006 New Revision: 35552 Modified: pypy/dist/pypy/tool/error.py Log: Fix bug reported by the test. Modified: pypy/dist/pypy/tool/error.py ============================================================================== --- pypy/dist/pypy/tool/error.py (original) +++ pypy/dist/pypy/tool/error.py Sun Dec 10 15:34:42 2006 @@ -21,7 +21,7 @@ show_lines_of_code=SHOW_DEFAULT_LINES_OF_CODE): if block is not None: if block is graph.returnblock: - return [''] + return [''] try: source = graph.source except AttributeError: @@ -114,8 +114,14 @@ msg = ["annotation of %r degenerated to SomeObject()" % (what,)] if position_key is not None: graph, block, operindex = position_key - oper = block.operations[operindex] - msg.append(str(oper)) + if operindex is not None: + oper = block.operations[operindex] + msg.append(str(oper)) + else: + msg.append("at the start of the block with input arguments:") + for v in block.inputargs: + s_v = annotator.binding(v, "(no annotation)") + msg.append("%8s: %s" % (v, s_v)) msg.append('') msg += source_lines(graph, block, operindex, long=True) From arigo at codespeak.net Sun Dec 10 15:41:28 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 10 Dec 2006 15:41:28 +0100 (CET) Subject: [pypy-svn] r35553 - in pypy/dist/pypy: objspace tool Message-ID: <20061210144128.582FD10071@code0.codespeak.net> Author: arigo Date: Sun Dec 10 15:41:25 2006 New Revision: 35553 Modified: pypy/dist/pypy/objspace/trace.py pypy/dist/pypy/tool/pydis.py pypy/dist/pypy/tool/stdlib_opcode.py Log: Fixes for the trace objspace. Modified: pypy/dist/pypy/objspace/trace.py ============================================================================== --- pypy/dist/pypy/objspace/trace.py (original) +++ pypy/dist/pypy/objspace/trace.py Sun Dec 10 15:41:25 2006 @@ -16,7 +16,7 @@ def __init__(self, frame): self.frame = frame self.code = frame.pycode - self.index = intmask(frame.next_instr) + self.index = intmask(frame.last_instr) class EnterFrame(object): def __init__(self, frame): Modified: pypy/dist/pypy/tool/pydis.py ============================================================================== --- pypy/dist/pypy/tool/pydis.py (original) +++ pypy/dist/pypy/tool/pydis.py Sun Dec 10 15:41:25 2006 @@ -8,11 +8,13 @@ import autopath import sys +from pypy.tool import stdlib_opcode from pypy.tool.stdlib_opcode import * -from pypy.tool.stdlib_opcode import __all__ as _opcodes_all -__all__ = ["dis","pydisassemble","distb","disco"] + _opcodes_all -del _opcodes_all +__all__ = ["dis","pydisassemble","distb","disco"] + stdlib_opcode.__all__ + +EXTENDED_ARG = stdlib_opcode.opcodedesc.EXTENDED_ARG.index + class Bytecode: def __init__(self, disresult, bytecodeindex, oparg, lineno): Modified: pypy/dist/pypy/tool/stdlib_opcode.py ============================================================================== --- pypy/dist/pypy/tool/stdlib_opcode.py (original) +++ pypy/dist/pypy/tool/stdlib_opcode.py Sun Dec 10 15:41:25 2006 @@ -1,7 +1,8 @@ # load opcode.py as pythonopcode from our own lib __all__ = ['opmap', 'opname', 'HAVE_ARGUMENT', - 'hasjrel', 'hasjabs', 'cmp_op'] + 'hasconst', 'hasname', 'hasjrel', 'hasjabs', + 'haslocal', 'hascompare', 'hasfree', 'cmp_op'] def load_opcode(): import py From ericvrp at codespeak.net Sun Dec 10 16:00:23 2006 From: ericvrp at codespeak.net (ericvrp at codespeak.net) Date: Sun, 10 Dec 2006 16:00:23 +0100 (CET) Subject: [pypy-svn] r35555 - in pypy/dist/pypy/jit/codegen: i386/test llvm llvm/test Message-ID: <20061210150023.5D17710069@code0.codespeak.net> Author: ericvrp Date: Sun Dec 10 16:00:22 2006 New Revision: 35555 Modified: pypy/dist/pypy/jit/codegen/i386/test/test_operation.py pypy/dist/pypy/jit/codegen/llvm/rgenop.py pypy/dist/pypy/jit/codegen/llvm/test/test_llvmjit.py pypy/dist/pypy/jit/codegen/llvm/test/test_operation.py Log: Actually share the operation tests. Still disabled because too many llvm operation missing. Modified: pypy/dist/pypy/jit/codegen/i386/test/test_operation.py ============================================================================== --- pypy/dist/pypy/jit/codegen/i386/test/test_operation.py (original) +++ pypy/dist/pypy/jit/codegen/i386/test/test_operation.py Sun Dec 10 16:00:22 2006 @@ -42,9 +42,11 @@ return tuple(map(conv, RI386GenOp.varsizeAllocToken(A))) -class TestBasic: +class I386TestBasicMixin(object): RGenOp = RGenOpPacked + +class BasicTests(object): def rgen(self, ll_function, argtypes): t = TranslationContext() t.buildannotator().build_types(ll_function, argtypes) @@ -221,7 +223,6 @@ assert fp(25, 3) == fn(25, 3) def test_float_arithmetic(self): - py.test.skip("floats in codegen/i386") for fn in [lambda x, y: bool(y), lambda x, y: bool(y - 2.0), lambda x, y: x + y, @@ -238,3 +239,9 @@ fp = self.rgen(fn, [float, float]) assert fp(40.0, 2.0) == fn(40.0, 2.0) assert fp(25.125, 1.5) == fn(25.125, 1.5) + + +class TestBasic(I386TestBasicMixin, + BasicTests): + pass + Modified: pypy/dist/pypy/jit/codegen/llvm/rgenop.py ============================================================================== --- pypy/dist/pypy/jit/codegen/llvm/rgenop.py (original) +++ pypy/dist/pypy/jit/codegen/llvm/rgenop.py Sun Dec 10 16:00:22 2006 @@ -1,3 +1,4 @@ +import py from pypy.rlib.objectmodel import specialize from pypy.rpython.lltypesystem import lltype, llmemory from pypy.jit.codegen.model import AbstractRGenOp, GenLabel, GenBuilder @@ -470,6 +471,8 @@ return 'int*' elif T is llmemory.Address: return 'int*' + if T is lltype.Float: + py.test.skip("not implemented: floats in the llvm back-end") elif T is lltype.Bool: return 'bool' else: Modified: pypy/dist/pypy/jit/codegen/llvm/test/test_llvmjit.py ============================================================================== --- pypy/dist/pypy/jit/codegen/llvm/test/test_llvmjit.py (original) +++ pypy/dist/pypy/jit/codegen/llvm/test/test_llvmjit.py Sun Dec 10 16:00:22 2006 @@ -1,5 +1,4 @@ import py -from sys import platform from os.path import dirname, join from pypy.translator.c.test.test_genc import compile from pypy.jit.codegen.llvm import llvmjit @@ -10,6 +9,12 @@ py.test.skip("can not load libllvmjit library (see ../README.TXT)") # +def skip_unsupported_platform(): + from sys import platform + if platform == 'darwin': + py.test.skip('dynamic vs. static library issue on Darwin. see: http://www.cocoadev.com/index.pl?ApplicationLinkingIssues for more information (FIXME)') + +# llsquare = '''int %square(int %n) { %n2 = mul int %n, %n ret int %n2 @@ -237,9 +242,7 @@ pass def test_execute_translation(): #put this one last because it takes the most time - if platform == 'darwin': - py.test.skip('dynamic vs. static library issue on Darwin. see: http://www.cocoadev.com/index.pl?ApplicationLinkingIssues for more information (FIXME)') - + skip_unsupported_platform() llvmjit.restart() def f(x): return execute(llsquare, 'square', x + 5) Modified: pypy/dist/pypy/jit/codegen/llvm/test/test_operation.py ============================================================================== --- pypy/dist/pypy/jit/codegen/llvm/test/test_operation.py (original) +++ pypy/dist/pypy/jit/codegen/llvm/test/test_operation.py Sun Dec 10 16:00:22 2006 @@ -1,12 +1,18 @@ import py -from pypy.jit.codegen.i386.test.test_operation import TestBasic +from pypy.jit.codegen.llvm.test.test_llvmjit import skip_unsupported_platform +from pypy.jit.codegen.i386.test.test_operation import BasicTests from pypy.jit.codegen.llvm.rgenop import RLLVMGenOp -py.test.skip("WIP") -class LLVMTestBasic(TestBasic): +skip_unsupported_platform() +py.test.skip('WIP') + +class LLVMTestBasicMixin(object): RGenOp = RLLVMGenOp +class TestBasic(LLVMTestBasicMixin, + BasicTests): + # for the individual tests see # ====> ../../../i386/test/test_operation.py From radix at codespeak.net Sun Dec 10 17:52:20 2006 From: radix at codespeak.net (radix at codespeak.net) Date: Sun, 10 Dec 2006 17:52:20 +0100 (CET) Subject: [pypy-svn] r35557 - pypy/dist/pypy/rlib/parsing Message-ID: <20061210165220.5E70F10069@code0.codespeak.net> Author: radix Date: Sun Dec 10 17:52:20 2006 New Revision: 35557 Modified: pypy/dist/pypy/rlib/parsing/tree.py Log: make the __repr__ output of Nonterminal match the actual initialization order. Modified: pypy/dist/pypy/rlib/parsing/tree.py ============================================================================== --- pypy/dist/pypy/rlib/parsing/tree.py (original) +++ pypy/dist/pypy/rlib/parsing/tree.py Sun Dec 10 17:52:20 2006 @@ -44,7 +44,7 @@ return "%s(%s)" % (self.symbol, ", ".join([str(c) for c in self.children])) def __repr__(self): - return "Nonterminal(%r, %r)" % (self.children, self.symbol) + return "Nonterminal(%r, %r)" % (self.symbol, self.children) def dot(self): yield '"%s" [label="%s"];' % (id(self), self.symbol) From ericvrp at codespeak.net Mon Dec 11 10:35:25 2006 From: ericvrp at codespeak.net (ericvrp at codespeak.net) Date: Mon, 11 Dec 2006 10:35:25 +0100 (CET) Subject: [pypy-svn] r35559 - in pypy/dist/pypy/jit/codegen/llvm: . test Message-ID: <20061211093525.3889910050@code0.codespeak.net> Author: ericvrp Date: Mon Dec 11 10:35:24 2006 New Revision: 35559 Modified: pypy/dist/pypy/jit/codegen/llvm/rgenop.py pypy/dist/pypy/jit/codegen/llvm/test/test_operation.py Log: Added int operations to jit/codegen/llvm to make arithmetic tests pass Modified: pypy/dist/pypy/jit/codegen/llvm/rgenop.py ============================================================================== --- pypy/dist/pypy/jit/codegen/llvm/rgenop.py (original) +++ pypy/dist/pypy/jit/codegen/llvm/rgenop.py Mon Dec 11 10:35:24 2006 @@ -298,12 +298,44 @@ def op_int_gt(self, gv_x, gv_y): return self._rgenop2_generic('setgt', gv_x, gv_y, 'bool') def op_int_ge(self, gv_x, gv_y): return self._rgenop2_generic('setge', gv_x, gv_y, 'bool') - #def op_int_neg(self, gv_x): - #def op_int_abs(self, gv_x): - #def op_int_invert(self, gv_x): - #def op_int_lshift(self, gv_x, gv_y): - #def op_int_rshift(self, gv_x, gv_y): - #def op_bool_not(self, gv_x): + def op_int_lshift(self, gv_x, gv_y): + gv_y_ubyte = Var('ubyte') + self.asm.append(' %s=cast %s to ubyte' % (gv_y_ubyte.operand2(), gv_y.operand())) + gv_result = Var(gv_x.type) + self.asm.append(' %s=shl %s,%s' % ( + gv_result.operand2(), gv_x.operand(), gv_y_ubyte.operand())) + return gv_result + + def op_int_rshift(self, gv_x, gv_y): + gv_y_ubyte = Var('ubyte') + self.asm.append(' %s=cast %s to ubyte' % (gv_y_ubyte.operand2(), gv_y.operand())) + gv_result = Var(gv_x.type) + self.asm.append(' %s=shr %s,%s' % ( + gv_result.operand2(), gv_x.operand(), gv_y_ubyte.operand())) + return gv_result + + def _rgenop1_generic(self, llvm_opcode, gv_x, restype='int'): + log('%s Builder._rgenop1_generic %s %s' % ( + self.block.label, llvm_opcode, gv_x.operand())) + gv_result = Var(restype) + self.asm.append(' %s=%s %s' % ( + gv_result.operand2(), llvm_opcode, gv_x.operand())) + return gv_resulgv_comp.operand(), t + + def op_int_neg(self, gv_x): return self._rgenop2_generic('sub', IntConst(0), gv_x) + def op_int_invert(self, gv_x): return self._rgenop2_generic('xor', gv_x, IntConst(-1)) + + def op_int_abs(self, gv_x): + gv_comp = Var('bool') + gv_abs_pos = Var(gv_x.type) + gv_result = Var(gv_x.type) + self.asm.append(' %s=setgt %s,-1' % (gv_comp.operand2(), gv_x.operand())) + self.asm.append(' %s=sub %s 0,%s' % (gv_abs_pos.operand2(), gv_x.type, gv_x.operand2())) + self.asm.append(' %s=select %s,%s,%s' % ( + gv_result.operand2(), gv_comp.operand(), gv_x.operand(), gv_abs_pos.operand())) + return gv_result + + #def op_bool_not(self, gv_x): #use select, xor or sub #def op_cast_bool_to_int(self, gv_x): def enter_next_block(self, kinds, args_gv): Modified: pypy/dist/pypy/jit/codegen/llvm/test/test_operation.py ============================================================================== --- pypy/dist/pypy/jit/codegen/llvm/test/test_operation.py (original) +++ pypy/dist/pypy/jit/codegen/llvm/test/test_operation.py Mon Dec 11 10:35:24 2006 @@ -5,7 +5,7 @@ skip_unsupported_platform() -py.test.skip('WIP') +#py.test.skip('WIP') class LLVMTestBasicMixin(object): RGenOp = RLLVMGenOp @@ -16,5 +16,15 @@ # for the individual tests see # ====> ../../../i386/test/test_operation.py - pass + def skip(self): + py.test.skip('WIP') + + test_comparison = skip + test_char_comparison = skip + test_unichar_comparison = skip + test_char_array = skip + test_char_varsize_array = skip + test_unichar_array = skip + test_char_unichar_fields = skip + test_unsigned = skip From guido at codespeak.net Mon Dec 11 11:04:11 2006 From: guido at codespeak.net (guido at codespeak.net) Date: Mon, 11 Dec 2006 11:04:11 +0100 (CET) Subject: [pypy-svn] r35560 - in pypy/dist/pypy/tool/build: . bin test Message-ID: <20061211100411.9186710063@code0.codespeak.net> Author: guido Date: Mon Dec 11 11:04:10 2006 New Revision: 35560 Modified: pypy/dist/pypy/tool/build/bin/client pypy/dist/pypy/tool/build/client.py pypy/dist/pypy/tool/build/test/test_client.py Log: Re-added ChannelWrapper to take care of building and sending the zip in chunks rather than building it fully in memory and sending it over as a whole, removed some debug prints (or log writes actually), whitespace. Modified: pypy/dist/pypy/tool/build/bin/client ============================================================================== --- pypy/dist/pypy/tool/build/bin/client (original) +++ pypy/dist/pypy/tool/build/bin/client Mon Dec 11 11:04:10 2006 @@ -1,7 +1,5 @@ #!/usr/bin/python -BUFSIZE = 1024 - import path import sys import random @@ -26,8 +24,6 @@ path=buildconfig.path, port=buildconfig.port) - - print channel.receive() # welcome message try: try: Modified: pypy/dist/pypy/tool/build/client.py ============================================================================== --- pypy/dist/pypy/tool/build/client.py (original) +++ pypy/dist/pypy/tool/build/client.py Mon Dec 11 11:04:10 2006 @@ -27,14 +27,9 @@ thread.start_new_thread(self.wait_until_done, (info,)) def wait_until_done(self, info): - efp = open('/tmp/foo', 'w') - efp.write(repr(info) + '\n') buildpath = self.server.get_new_buildpath(info) - efp.flush() if not self.testing: - efp.write('2\n') - efp.flush() fp = buildpath.zipfile.open('w') try: while True: @@ -49,13 +44,8 @@ finally: fp.close() - efp.write('3\n') - efp.flush() self.server.compilation_done(info, buildpath) self.busy_on = None - efp.write(repr(info)) - efp.flush() - efp.close() initcode = """ import sys @@ -89,11 +79,34 @@ channel = conference.remote_exec(initcode % (path, sysinfo, testing)) return channel +class ChannelWrapper(object): + """ wrapper around a channel + + implements (a small part of) the file interface, sends the data + over the wire in chunks, ending with a None + """ + def __init__(self, channel): + self.channel = channel + self.loc = 0 + + def write(self, data): + self.loc += len(data) + self.channel.send(data) + + def close(self): + self.channel.send(None) + + def tell(self): + return self.loc + + def flush(self): + pass + def zip_result(res_dir, channel): - # channelwrapper = ChannelWrapper(channel) - buf = StringIO() - zip = ZipFile(buf, 'w') - zip.writestr('pypy-c', open('pypy-c').read()) + channelwrapper = ChannelWrapper(channel) + zip = ZipFile(channelwrapper, 'w') + # might not be C pypy... + # zip.writestr('pypy-c', res_dir.join('testing_1/testing_1').read()) for fpath in res_dir.visit(): try: zip.writestr(fpath.relto(res_dir), fpath.read()) @@ -101,6 +114,5 @@ print exc continue zip.close() - channel.send(buf.getvalue()) channel.send(None) Modified: pypy/dist/pypy/tool/build/test/test_client.py ============================================================================== --- pypy/dist/pypy/tool/build/test/test_client.py (original) +++ pypy/dist/pypy/tool/build/test/test_client.py Mon Dec 11 11:04:10 2006 @@ -35,7 +35,7 @@ # available on its own channel, with our FakeChannel it has data rightaway, # though (the channel out and in are the same, and we just sent 'info' # over the out one) - time.sleep(1) + time.sleep(1) done = svr._done.pop() From guido at codespeak.net Mon Dec 11 11:43:12 2006 From: guido at codespeak.net (guido at codespeak.net) Date: Mon, 11 Dec 2006 11:43:12 +0100 (CET) Subject: [pypy-svn] r35562 - in pypy/dist/pypy/tool/build: . bin builds test Message-ID: <20061211104312.70C4A10068@code0.codespeak.net> Author: guido Date: Mon Dec 11 11:43:09 2006 New Revision: 35562 Modified: pypy/dist/pypy/tool/build/bin/client pypy/dist/pypy/tool/build/builds/ (props changed) pypy/dist/pypy/tool/build/client.py pypy/dist/pypy/tool/build/config.py pypy/dist/pypy/tool/build/conftest.py pypy/dist/pypy/tool/build/server.py pypy/dist/pypy/tool/build/test/test_client.py pypy/dist/pypy/tool/build/test/test_pypybuilder.py Log: Updated functional tests, added some more warnings about time.sleep(), added missing test for channelwrapper, added build subdirs to svn:ignore, some whitespace and cleanups, being a bit extra careful in shutting down client and server (still sometimes exceptions in remote processes on shutdown, though), using better config defaults. Modified: pypy/dist/pypy/tool/build/bin/client ============================================================================== --- pypy/dist/pypy/tool/build/bin/client (original) +++ pypy/dist/pypy/tool/build/bin/client Mon Dec 11 11:43:09 2006 @@ -38,7 +38,7 @@ ) sysinfo, compileinfo = data # XXX we should compile here, using data dict for info - print 'compilation requested for info %r, now faking that' % ( + print 'compilation requested for info %r\n\nbuilding...' % ( data,) config = pypyoption.get_pypy_config() config.override(compileinfo) Modified: pypy/dist/pypy/tool/build/client.py ============================================================================== --- pypy/dist/pypy/tool/build/client.py (original) +++ pypy/dist/pypy/tool/build/client.py Mon Dec 11 11:43:09 2006 @@ -1,7 +1,6 @@ import thread import py from zipfile import ZipFile -from cStringIO import StringIO class PPBClient(object): @@ -33,6 +32,7 @@ fp = buildpath.zipfile.open('w') try: while True: + # read data in chunks try: chunk = self.channel.receive() except EOFError: @@ -58,12 +58,15 @@ client = PPBClient(channel, %r, %r) client.sit_and_wait() except: - import sys, traceback - exc, e, tb = sys.exc_info() - channel.send(str(exc) + ' - ' + str(e)) - for line in traceback.format_tb(tb): - channel.send(line[:-1]) - del tb + try: + import sys, traceback + exc, e, tb = sys.exc_info() + channel.send(str(exc) + ' - ' + str(e)) + for line in traceback.format_tb(tb): + channel.send(line[:-1]) + del tb + except: + pass finally: channel.close() """ @@ -114,5 +117,3 @@ print exc continue zip.close() - channel.send(None) - Modified: pypy/dist/pypy/tool/build/config.py ============================================================================== --- pypy/dist/pypy/tool/build/config.py (original) +++ pypy/dist/pypy/tool/build/config.py Mon Dec 11 11:43:09 2006 @@ -3,7 +3,7 @@ packageparent = py.magic.autopath().dirpath().dirpath().dirpath().dirpath() # general settings, used by both server and client -server = '134.99.66.245' +server = 'localhost' port = 12321 path = [str(packageparent)] @@ -25,9 +25,9 @@ # settings for the server projectname = 'pypy' buildpath = packageparent.join('/pypy/tool/build/builds') -mailhost = '127.0.0.1' +mailhost = 'localhost' mailport = 25 -mailfrom = 'johnny at johnnydebris.net' +mailfrom = 'pypybuilds at codespeak.net' # settings for the tests testpath = [str(py.magic.autopath().dirpath().dirpath())] Modified: pypy/dist/pypy/tool/build/conftest.py ============================================================================== --- pypy/dist/pypy/tool/build/conftest.py (original) +++ pypy/dist/pypy/tool/build/conftest.py Mon Dec 11 11:43:09 2006 @@ -3,18 +3,18 @@ ReSTChecker mypath = py.magic.autopath().dirpath() -Option = py.test.Config.Option -option = py.test.Config.addoptions("pypybuilder test options", +Option = py.test.Config.Option +option = py.test.Config.addoptions("pypybuilder test options", Option('', '--functional', action="store_true", dest="functional", default=False, help="run pypybuilder functional tests" ), -) +) py.test.pypybuilder_option = option class Directory(Dir): def run(self): if self.fspath == mypath: - return ['README.txt', 'test'] + return ['test'] return super(Directory, self).run() Modified: pypy/dist/pypy/tool/build/server.py ============================================================================== --- pypy/dist/pypy/tool/build/server.py (original) +++ pypy/dist/pypy/tool/build/server.py Mon Dec 11 11:43:09 2006 @@ -314,12 +314,18 @@ server.serve_forever() except: - import sys, traceback - exc, e, tb = sys.exc_info() - channel.send(str(exc) + ' - ' + str(e)) - for line in traceback.format_tb(tb): - channel.send(line[:1]) - del tb + try: + import sys, traceback + exc, e, tb = sys.exc_info() + channel.send(str(exc) + ' - ' + str(e)) + for line in traceback.format_tb(tb): + channel.send(line[:1]) + del tb + except: + try: + channel.close() + except: + pass finally: channel.close() """ Modified: pypy/dist/pypy/tool/build/test/test_client.py ============================================================================== --- pypy/dist/pypy/tool/build/test/test_client.py (original) +++ pypy/dist/pypy/tool/build/test/test_client.py Mon Dec 11 11:43:09 2006 @@ -41,3 +41,20 @@ assert done[0] == info assert done[1] == (temp / 'build-0') + +def test_channelwrapper(): + class FakeChannel(object): + def __init__(self): + self.buffer = [] + def send(self, data): + self.buffer.append(data) + c = FakeChannel() + cw = client.ChannelWrapper(c) + assert cw.tell() == 0 + cw.write('foo') + cw.write('bar') + assert cw.tell() == 6 + cw.write('baz') + cw.close() + assert c.buffer == ['foo', 'bar', 'baz', None] + Modified: pypy/dist/pypy/tool/build/test/test_pypybuilder.py ============================================================================== --- pypy/dist/pypy/tool/build/test/test_pypybuilder.py (original) +++ pypy/dist/pypy/tool/build/test/test_pypybuilder.py Mon Dec 11 11:43:09 2006 @@ -4,9 +4,13 @@ from pypy.config import config as pypyconfig import py +# XXX NOTE: if you encounter failing tests on a slow system, you may want to +# increase the sleep interval a bit to see if that helps... +SLEEP_INTERVAL = 1.0 + def _get_sysconfig(): return pypyconfig.Config( - pypyconfig.OptionDescription('foo', [ + pypyconfig.OptionDescription('foo', '', [ pypyconfig.ChoiceOption('foo', 'foo', [1,2,3], 1), ]) ) @@ -21,16 +25,14 @@ # system, but for instance contains time.sleep()s to make sure all threads # get the time to perform tasks and such... - sleep_interval = 0.3 - # first initialize a server sgw = py.execnet.PopenGateway() temppath = py.test.ensuretemp('pypybuilder-functional') - sc = server.init(sgw, port=config.port, path=config.testpath, - buildpath=str(temppath)) + sc = server.init(sgw, port=config.port, path=config.testpath, + buildpath=str(temppath)) # give the server some time to wake up - py.std.time.sleep(sleep_interval) + py.std.time.sleep(SLEEP_INTERVAL) # then two clients, both with different system info sysconfig1 = _get_sysconfig() @@ -43,7 +45,7 @@ cc2 = client.init(cgw2, sysconfig2, port=config.port, testing=True) # give the clients some time to register themselves - py.std.time.sleep(sleep_interval) + py.std.time.sleep(SLEEP_INTERVAL) # now we're going to send some compile jobs code = """ @@ -58,11 +60,11 @@ compconf = execnetconference.conference(compgw, config.port) # this one should fail because there's no client found for foo = 3 - compc = compconf.remote_exec(code % (config.testpath, 'foo1 at bar.com', + compc = compconf.remote_exec(code % (config.testpath, 'foo1 at bar.com', {'foo': 3})) # sorry... - py.std.time.sleep(sleep_interval) + py.std.time.sleep(SLEEP_INTERVAL) ret = compc.receive() assert not ret[0] @@ -73,18 +75,18 @@ {'foo': 1})) # and another one - py.std.time.sleep(sleep_interval) + py.std.time.sleep(SLEEP_INTERVAL) ret = compc.receive() assert not ret[0] assert ret[1].find('found a suitable client') > -1 # the messages may take a bit to arrive, too - py.std.time.sleep(sleep_interval) + py.std.time.sleep(SLEEP_INTERVAL) # client 1 should by now have received the info to build for cc1.receive() # 'welcome' - ret = cc1.receive() + ret = cc1.receive() assert ret == ({'foo': 1}, {}) # this should have created a package in the temp dir @@ -97,7 +99,7 @@ cc3 = client.init(cgw3, sysconfig3, port=config.port, testing=True) # again a bit of waiting may be desired - py.std.time.sleep(sleep_interval) + py.std.time.sleep(SLEEP_INTERVAL) # _try_queued() should check whether there are new clients available for # queued jobs @@ -115,8 +117,7 @@ compgw2 = py.execnet.PopenGateway() compconf2 = execnetconference.conference(compgw2, config.port) - compc2 = compconf2.remote_exec(code % (config.testpath, sleep_interval)) - + compc2 = compconf2.remote_exec(code % (config.testpath, SLEEP_INTERVAL)) # we check whether all emails are now sent, since after adding the third # client, and calling _try_queued(), both jobs should have been processed From ericvrp at codespeak.net Mon Dec 11 12:43:01 2006 From: ericvrp at codespeak.net (ericvrp at codespeak.net) Date: Mon, 11 Dec 2006 12:43:01 +0100 (CET) Subject: [pypy-svn] r35563 - in pypy/dist/pypy/jit/codegen/llvm: . test Message-ID: <20061211114301.F32DF10033@code0.codespeak.net> Author: ericvrp Date: Mon Dec 11 12:43:00 2006 New Revision: 35563 Modified: pypy/dist/pypy/jit/codegen/llvm/rgenop.py pypy/dist/pypy/jit/codegen/llvm/test/test_operation.py Log: - Most int,unsigned,char,unichar and float operations implemented for jit/codegen/llvm. - All casts between bool,char,unichar,int,uint and float implemented. - All comparisons implemented. There are two issues that I tried documenting in llvm/test/test_operation.py . Modified: pypy/dist/pypy/jit/codegen/llvm/rgenop.py ============================================================================== --- pypy/dist/pypy/jit/codegen/llvm/rgenop.py (original) +++ pypy/dist/pypy/jit/codegen/llvm/rgenop.py Mon Dec 11 12:43:00 2006 @@ -110,7 +110,7 @@ # check the types for debugging sourcevartypes = [var.type for var in sourcevars] targetvartypes = [var.type for var in self.inputargs] - assert sourcevartypes == targetvartypes + #XXX ERIC assert sourcevartypes == targetvartypes # Check if the source block jumps to 'self' from multiple # positions: in this case we need an intermediate block... @@ -283,20 +283,14 @@ gv_result.operand2(), llvm_opcode, gv_arg1.operand(), gv_arg2.operand2())) return gv_result - def op_int_add(self, gv_x, gv_y): return self._rgenop2_generic('add' , gv_x, gv_y) - def op_int_sub(self, gv_x, gv_y): return self._rgenop2_generic('sub' , gv_x, gv_y) - def op_int_mul(self, gv_x, gv_y): return self._rgenop2_generic('mul' , gv_x, gv_y) - def op_int_floordiv(self, gv_x, gv_y): return self._rgenop2_generic('sdiv' , gv_x, gv_y) - def op_int_mod(self, gv_x, gv_y): return self._rgenop2_generic('rem' , gv_x, gv_y) - def op_int_and(self, gv_x, gv_y): return self._rgenop2_generic('and' , gv_x, gv_y) - def op_int_or(self, gv_x, gv_y): return self._rgenop2_generic('or' , gv_x, gv_y) - def op_int_xor(self, gv_x, gv_y): return self._rgenop2_generic('xor' , gv_x, gv_y) - def op_int_lt(self, gv_x, gv_y): return self._rgenop2_generic('setlt', gv_x, gv_y, 'bool') - def op_int_le(self, gv_x, gv_y): return self._rgenop2_generic('setle', gv_x, gv_y, 'bool') - def op_int_eq(self, gv_x, gv_y): return self._rgenop2_generic('seteq', gv_x, gv_y, 'bool') - def op_int_ne(self, gv_x, gv_y): return self._rgenop2_generic('setne', gv_x, gv_y, 'bool') - def op_int_gt(self, gv_x, gv_y): return self._rgenop2_generic('setgt', gv_x, gv_y, 'bool') - def op_int_ge(self, gv_x, gv_y): return self._rgenop2_generic('setge', gv_x, gv_y, 'bool') + def op_int_add(self, gv_x, gv_y): return self._rgenop2_generic('add' , gv_x, gv_y) + def op_int_sub(self, gv_x, gv_y): return self._rgenop2_generic('sub' , gv_x, gv_y) + def op_int_mul(self, gv_x, gv_y): return self._rgenop2_generic('mul' , gv_x, gv_y) + def op_int_floordiv(self, gv_x, gv_y): return self._rgenop2_generic('sdiv', gv_x, gv_y) + def op_int_mod(self, gv_x, gv_y): return self._rgenop2_generic('rem' , gv_x, gv_y) + def op_int_and(self, gv_x, gv_y): return self._rgenop2_generic('and' , gv_x, gv_y) + def op_int_or(self, gv_x, gv_y): return self._rgenop2_generic('or' , gv_x, gv_y) + def op_int_xor(self, gv_x, gv_y): return self._rgenop2_generic('xor' , gv_x, gv_y) def op_int_lshift(self, gv_x, gv_y): gv_y_ubyte = Var('ubyte') @@ -314,6 +308,31 @@ gv_result.operand2(), gv_x.operand(), gv_y_ubyte.operand())) return gv_result + op_uint_add = op_float_add = op_int_add + op_uint_sub = op_float_sub = op_int_sub + op_uint_mul = op_float_mul = op_int_mul + op_uint_floordiv = op_float_floordiv = op_int_floordiv + op_uint_mod = op_int_mod + op_uint_and = op_int_and + op_uint_or = op_int_or + op_uint_xor = op_int_xor + op_uint_lshift = op_int_lshift + op_uint_rshift = op_int_rshift + + def op_int_lt(self, gv_x, gv_y): return self._rgenop2_generic('setlt', gv_x, gv_y, 'bool') + def op_int_le(self, gv_x, gv_y): return self._rgenop2_generic('setle', gv_x, gv_y, 'bool') + def op_int_eq(self, gv_x, gv_y): return self._rgenop2_generic('seteq', gv_x, gv_y, 'bool') + def op_int_ne(self, gv_x, gv_y): return self._rgenop2_generic('setne', gv_x, gv_y, 'bool') + def op_int_gt(self, gv_x, gv_y): return self._rgenop2_generic('setgt', gv_x, gv_y, 'bool') + def op_int_ge(self, gv_x, gv_y): return self._rgenop2_generic('setge', gv_x, gv_y, 'bool') + + op_char_lt = op_uint_lt = op_float_lt = op_int_lt + op_char_le = op_uint_le = op_float_le = op_int_le + op_char_eq = op_uint_eq = op_float_eq = op_unichar_eq = op_int_eq + op_char_ne = op_uint_ne = op_float_ne = op_unichar_ne = op_int_ne + op_char_gt = op_uint_gt = op_float_gt = op_int_gt + op_char_ge = op_uint_ge = op_float_ge = op_int_ge + def _rgenop1_generic(self, llvm_opcode, gv_x, restype='int'): log('%s Builder._rgenop1_generic %s %s' % ( self.block.label, llvm_opcode, gv_x.operand())) @@ -324,6 +343,7 @@ def op_int_neg(self, gv_x): return self._rgenop2_generic('sub', IntConst(0), gv_x) def op_int_invert(self, gv_x): return self._rgenop2_generic('xor', gv_x, IntConst(-1)) + def op_uint_invert(self, gv_x): return self._rgenop2_generic('xor', gv_x, IntConst((1<<32)-1)) def op_int_abs(self, gv_x): gv_comp = Var('bool') @@ -335,8 +355,56 @@ gv_result.operand2(), gv_comp.operand(), gv_x.operand(), gv_abs_pos.operand())) return gv_result - #def op_bool_not(self, gv_x): #use select, xor or sub - #def op_cast_bool_to_int(self, gv_x): + #def op_bool_not(self, gv_x): #use select, xor or sub XXXX todo: did not see a test for this + + def _cast_to(self, gv_x, restype='int'): + gv_result = Var(restype) + self.asm.append(' %s=cast %s to %s' % ( + gv_result.operand2(), gv_x.operand(), restype)) + return gv_result + + def _cast_to_bool(self, gv_x): return self._cast_to(gv_x, 'bool') + def _cast_to_char(self, gv_x): return self._cast_to(gv_x, 'ubyte') + def _cast_to_unichar(self, gv_x): return self._cast_to(gv_x, 'int') + def _cast_to_int(self, gv_x): return self._cast_to(gv_x, 'int') + def _cast_to_uint(self, gv_x): return self._cast_to(gv_x, 'uint') + def _cast_to_float(self, gv_x): return self._cast_to(gv_x, 'float') + + op_cast_char_to_bool = _cast_to_bool + op_cast_unichar_to_bool = _cast_to_bool + op_cast_int_to_bool = _cast_to_bool + op_cast_uint_to_bool = _cast_to_bool + op_cast_float_to_bool = _cast_to_bool + + op_cast_bool_to_char = _cast_to_char + op_cast_unichar_to_char = _cast_to_char + op_cast_int_to_char = _cast_to_char + op_cast_uint_to_char = _cast_to_char + op_cast_float_to_char = _cast_to_char + + op_cast_bool_to_unichar = _cast_to_unichar + op_cast_char_to_unichar = _cast_to_unichar + op_cast_int_to_unichar = _cast_to_unichar + op_cast_uint_to_unichar = _cast_to_unichar + op_cast_float_to_unichar = _cast_to_unichar + + op_cast_bool_to_int = _cast_to_int + op_cast_char_to_int = _cast_to_int + op_cast_unichar_to_int = _cast_to_int + op_cast_uint_to_int = _cast_to_int + op_cast_float_to_int = _cast_to_int + + op_cast_bool_to_uint = _cast_to_uint + op_cast_char_to_uint = _cast_to_uint + op_cast_unichar_to_uint = _cast_to_uint + op_cast_int_to_uint = _cast_to_uint + op_cast_float_to_uint = _cast_to_uint + + op_cast_bool_to_float = _cast_to_float + op_cast_char_to_float = _cast_to_float + op_cast_unichar_to_float = _cast_to_float + op_cast_int_to_float = _cast_to_float + op_cast_uint_to_float = _cast_to_float def enter_next_block(self, kinds, args_gv): # if nextlabel is None, it means that we are currently @@ -380,12 +448,18 @@ gv_condition.operand(), targetbuilder.nextlabel, self.nextlabel)) return targetbuilder - def op_int_is_true(self, gv_x): - log('%s Build.op_int_is_true %s' % (self.block.label, gv_x.operand())) + def _is_true(self, gv_x, nullstr='0'): + log('%s Builder._is_true %s' % (self.block.label, gv_x.operand())) gv_result = Var('bool') - self.asm.append(' %s=setne %s,0' % (gv_result.operand2(), gv_x.operand())) + self.asm.append(' %s=setne %s,%s' % ( + gv_result.operand2(), gv_x.operand(), nullstr)) return gv_result + op_bool_is_true = op_char_is_true = op_unichar_is_true = op_int_is_true =\ + op_uint_is_true = _is_true + + def op_float_is_true(self, gv_x): return self._is_true(gv_x, '0.0') + def genop_call(self, sigtoken, gv_fnptr, args_gv): log('%s Builder.genop_call %s,%s,%s' % ( self.block.label, sigtoken, gv_fnptr, [v.operand() for v in args_gv])) @@ -503,12 +577,16 @@ return 'int*' elif T is llmemory.Address: return 'int*' - if T is lltype.Float: - py.test.skip("not implemented: floats in the llvm back-end") - elif T is lltype.Bool: + if T is lltype.Bool: return 'bool' + elif T is lltype.Char: + return 'ubyte' + elif T is lltype.Unsigned: + return 'uint' + elif T is lltype.Float: + return 'float' else: - return 'int' + return 'int' #Signed/UniChar/Void @staticmethod @specialize.memo() Modified: pypy/dist/pypy/jit/codegen/llvm/test/test_operation.py ============================================================================== --- pypy/dist/pypy/jit/codegen/llvm/test/test_operation.py (original) +++ pypy/dist/pypy/jit/codegen/llvm/test/test_operation.py Mon Dec 11 12:43:00 2006 @@ -14,17 +14,23 @@ BasicTests): # for the individual tests see - # ====> ../../../i386/test/test_operation.py + # ====> ../../i386/test/test_operation.py def skip(self): py.test.skip('WIP') - test_comparison = skip - test_char_comparison = skip - test_unichar_comparison = skip + test_unsigned = skip + #XXX -r_uint(n) generated op_int_sub(0,n) , why not op_uint_sub? + + test_float_arithmetic = skip + #XXX bool(f - 2.0) generated op_float_sub(f,IntConst(2)) , why not FloatConst(2.0) ? + # E assert fp(40.0, 2.0) == fn(40.0, 2.0) + # > ArgumentError: argument 1: exceptions.TypeError: int expected instead of float instance + + # [/mnt/hdb3/projects.eric/pypy-dist/pypy/jit/codegen/i386/test/test_operation.py:240] + test_char_array = skip test_char_varsize_array = skip test_unichar_array = skip test_char_unichar_fields = skip - test_unsigned = skip From guido at codespeak.net Mon Dec 11 13:31:47 2006 From: guido at codespeak.net (guido at codespeak.net) Date: Mon, 11 Dec 2006 13:31:47 +0100 (CET) Subject: [pypy-svn] r35565 - in pypy/dist/pypy/tool/build: . bin test Message-ID: <20061211123147.AB0AD10072@code0.codespeak.net> Author: guido Date: Mon Dec 11 13:31:43 2006 New Revision: 35565 Modified: pypy/dist/pypy/tool/build/bin/client pypy/dist/pypy/tool/build/client.py pypy/dist/pypy/tool/build/config.py pypy/dist/pypy/tool/build/server.py pypy/dist/pypy/tool/build/test/fake.py pypy/dist/pypy/tool/build/test/test_client.py pypy/dist/pypy/tool/build/test/test_pypybuilder.py pypy/dist/pypy/tool/build/test/test_server.py Log: Added mechanism to allow clients to decide to not accept a build request. Modified: pypy/dist/pypy/tool/build/bin/client ============================================================================== --- pypy/dist/pypy/tool/build/bin/client (original) +++ pypy/dist/pypy/tool/build/bin/client Mon Dec 11 13:31:43 2006 @@ -37,6 +37,15 @@ type(data),) ) sysinfo, compileinfo = data + accepting = True + for checker in config.client_checkers: + if not checker(sysinfo, compileinfo): + accepting = False + break + channel.send(accepting) + if not accepting: + print 'refusing compilation' + continue # XXX we should compile here, using data dict for info print 'compilation requested for info %r\n\nbuilding...' % ( data,) Modified: pypy/dist/pypy/tool/build/client.py ============================================================================== --- pypy/dist/pypy/tool/build/client.py (original) +++ pypy/dist/pypy/tool/build/client.py Mon Dec 11 13:31:43 2006 @@ -23,7 +23,10 @@ """send a compile job to the client side""" self.busy_on = info self.channel.send(info) - thread.start_new_thread(self.wait_until_done, (info,)) + accepted = self.channel.receive() + if accepted: + thread.start_new_thread(self.wait_until_done, (info,)) + return accepted def wait_until_done(self, info): buildpath = self.server.get_new_buildpath(info) Modified: pypy/dist/pypy/tool/build/config.py ============================================================================== --- pypy/dist/pypy/tool/build/config.py (original) +++ pypy/dist/pypy/tool/build/config.py Mon Dec 11 13:31:43 2006 @@ -32,3 +32,7 @@ # settings for the tests testpath = [str(py.magic.autopath().dirpath().dirpath())] +# when considering a compile job, the checkers below will be called (args +# sysinfo, compileinfo), if one of them returns False the compilation will +# not be accepted +client_checkers = [] Modified: pypy/dist/pypy/tool/build/server.py ============================================================================== --- pypy/dist/pypy/tool/build/server.py (original) +++ pypy/dist/pypy/tool/build/server.py Mon Dec 11 13:31:43 2006 @@ -211,8 +211,9 @@ info, client ) ) - client.compile(info) - return True + accepted = client.compile(info) + if accepted: + return True self._channel.send( 'no suitable client available for compilation with info %r' % ( info, Modified: pypy/dist/pypy/tool/build/test/fake.py ============================================================================== --- pypy/dist/pypy/tool/build/test/fake.py (original) +++ pypy/dist/pypy/tool/build/test/fake.py Mon Dec 11 13:31:43 2006 @@ -27,6 +27,7 @@ self.channel.send('%s: %r' % (k, v)) self.channel.send(None) self.busy_on = info + return True class FakeServer(object): def __init__(self, builddirpath): Modified: pypy/dist/pypy/tool/build/test/test_client.py ============================================================================== --- pypy/dist/pypy/tool/build/test/test_client.py (original) +++ pypy/dist/pypy/tool/build/test/test_client.py Mon Dec 11 13:31:43 2006 @@ -26,8 +26,11 @@ def test_compile(): info = ({'foo': 1}, {'bar': 2}) - c1.compile(info) - c1.channel.receive() + c1c.send(True) # notifying we 'accept' the compile + accepted = c1.compile(info) + assert accepted + ret = c1.channel.receive() + assert ret == info # this was still in the buffer c1.channel.send('foo bar') c1.channel.send(None) @@ -58,3 +61,9 @@ cw.close() assert c.buffer == ['foo', 'bar', 'baz', None] +def test_failed_checker(): + info = ({'foo': 1}, {'bar': 2}) + c1c.send(False) # notifying we _don't_ 'accept' the compile + accepted = c1.compile(info) + assert not accepted + Modified: pypy/dist/pypy/tool/build/test/test_pypybuilder.py ============================================================================== --- pypy/dist/pypy/tool/build/test/test_pypybuilder.py (original) +++ pypy/dist/pypy/tool/build/test/test_pypybuilder.py Mon Dec 11 13:31:43 2006 @@ -20,7 +20,7 @@ def test_functional_1(): if not py.test.pypybuilder_option.functional: py.test.skip('skipping functional test, use --functional to run it') - + # XXX this one is a bit messy, it's a quick functional test for the whole # system, but for instance contains time.sleep()s to make sure all threads # get the time to perform tasks and such... @@ -59,6 +59,12 @@ compgw = py.execnet.PopenGateway() compconf = execnetconference.conference(compgw, config.port) + # clients normally respond with a boolean on a compilation request... to + # allow the code to continue, already put some Trues (meaning 'I accept + # the job') in the buffers + cc1.send(True) + cc2.send(True) + # this one should fail because there's no client found for foo = 3 compc = compconf.remote_exec(code % (config.testpath, 'foo1 at bar.com', {'foo': 3})) @@ -98,6 +104,9 @@ cgw3 = py.execnet.PopenGateway() cc3 = client.init(cgw3, sysconfig3, port=config.port, testing=True) + # add True to the buffer just like we did for channels 1 and 2 + cc3.send(True) + # again a bit of waiting may be desired py.std.time.sleep(SLEEP_INTERVAL) Modified: pypy/dist/pypy/tool/build/test/test_server.py ============================================================================== --- pypy/dist/pypy/tool/build/test/test_server.py (original) +++ pypy/dist/pypy/tool/build/test/test_server.py Mon Dec 11 13:31:43 2006 @@ -50,17 +50,22 @@ ret = svr.compile('test at domain.com', (info, None)) assert not ret[0] assert ret[1].find('found a suitable client') > -1 - assert svr._channel.receive().find('going to send compile job') > -1 - assert c1.channel.receive() == 'foo: 1' - assert c1.channel.receive() is None + ret = svr._channel.receive() + assert ret.find('going to send compile job') > -1 + ret = c1.channel.receive() + assert ret == 'foo: 1' + ret = c1.channel.receive() + assert ret is None py.test.raises(IndexError, "c2.channel.receive()") svr.compile('test at domain.com', ({'foo': 3}, None)) - assert svr._channel.receive().find('no suitable client available') > -1 + ret = svr._channel.receive() + assert ret.find('no suitable client available') > -1 info = {'bar': [3]} - ret = svr.compile('test at domain.com', (info, None)) - assert svr._channel.receive().find('going to send') > -1 + svr.compile('test at domain.com', (info, None)) + ret = svr._channel.receive() + assert ret.find('going to send') > -1 assert c2.channel.receive() == 'bar: [3]' assert c2.channel.receive() is None py.test.raises(IndexError, "c1.channel.receive()") @@ -78,10 +83,13 @@ assert ret[0] assert isinstance(ret[1], str) assert BuildPath(ret[1]) == bp - assert svr._channel.receive().find('compilation done for') > -1 + ret = svr._channel.receive() + assert ret.find('compilation done for') > -1 for i in range(2): - assert svr._channel.receive().find('going to send email to') > -1 - assert svr._channel.receive().find('already a build for this info') > -1 + ret = svr._channel.receive() + assert ret.find('going to send email to') > -1 + ret = svr._channel.receive() + assert ret.find('already a build for this info') > -1 def test_buildpath(): tempdir = py.test.ensuretemp('pypybuilder-buildpath') From mwh at codespeak.net Mon Dec 11 13:32:07 2006 From: mwh at codespeak.net (mwh at codespeak.net) Date: Mon, 11 Dec 2006 13:32:07 +0100 (CET) Subject: [pypy-svn] r35566 - pypy/dist/pypy/interpreter Message-ID: <20061211123207.E0AFC10072@code0.codespeak.net> Author: mwh Date: Mon Dec 11 13:32:04 2006 New Revision: 35566 Modified: pypy/dist/pypy/interpreter/pyframe.py pypy/dist/pypy/interpreter/pyopcode.py Log: reinsert some resume_points. this certainly won't fix the sstackless build, but it's a stop on that way... Modified: pypy/dist/pypy/interpreter/pyframe.py ============================================================================== --- pypy/dist/pypy/interpreter/pyframe.py (original) +++ pypy/dist/pypy/interpreter/pyframe.py Mon Dec 11 13:32:04 2006 @@ -99,6 +99,7 @@ # the YIELD_VALUE instruction. next_instr = self.last_instr + 1 w_exitvalue = self.dispatch(code, next_instr, executioncontext) + rstack.resume_point("execute_frame", self, executioncontext, returns=w_exitvalue) executioncontext.return_trace(self, w_exitvalue) # on exit, we try to release self.last_exception -- breaks an # obvious reference cycle, so it helps refcounting implementations Modified: pypy/dist/pypy/interpreter/pyopcode.py ============================================================================== --- pypy/dist/pypy/interpreter/pyopcode.py (original) +++ pypy/dist/pypy/interpreter/pyopcode.py Mon Dec 11 13:32:04 2006 @@ -183,6 +183,8 @@ # dispatch to the opcode method meth = getattr(self, opdesc.methodname) res = meth(oparg, next_instr) + if opcode == opcodedesc.CALL_FUNCTION.index: + rstack.resume_point("dispatch_call", self, co_code, next_instr, ec) # !! warning, for the annotator the next line is not # comparing an int and None - you can't do that. # Instead, it's constant-folded to either True or False From santagada at codespeak.net Mon Dec 11 13:36:17 2006 From: santagada at codespeak.net (santagada at codespeak.net) Date: Mon, 11 Dec 2006 13:36:17 +0100 (CET) Subject: [pypy-svn] r35567 - pypy/dist/pypy/lang/js Message-ID: <20061211123617.AB81110078@code0.codespeak.net> Author: santagada Date: Mon Dec 11 13:36:14 2006 New Revision: 35567 Modified: pypy/dist/pypy/lang/js/astgen.py Log: simple mistake... unnamed functions don't have a name Modified: pypy/dist/pypy/lang/js/astgen.py ============================================================================== --- pypy/dist/pypy/lang/js/astgen.py (original) +++ pypy/dist/pypy/lang/js/astgen.py Mon Dec 11 13:36:14 2006 @@ -175,8 +175,8 @@ return Comma(from_dict(d['0']),from_dict(d['1'])) elif tp == 'DOT': return Dot(from_dict(d['0']), from_dict(d['1'])) - elif tp == 'FUNCTION': - name = d['name'] + elif tp == 'FUNCTION': + name = d.get('name', '') scope = scope_manager.enter_scope() body = from_dict(d['body']) if d['params'] == '': From guido at codespeak.net Mon Dec 11 13:46:31 2006 From: guido at codespeak.net (guido at codespeak.net) Date: Mon, 11 Dec 2006 13:46:31 +0100 (CET) Subject: [pypy-svn] r35568 - in pypy/dist/pypy/tool/build: . test Message-ID: <20061211124631.683F71007D@code0.codespeak.net> Author: guido Date: Mon Dec 11 13:46:29 2006 New Revision: 35568 Modified: pypy/dist/pypy/tool/build/client.py pypy/dist/pypy/tool/build/server.py pypy/dist/pypy/tool/build/test/fake.py pypy/dist/pypy/tool/build/test/test_client.py Log: Made that refusals (using the checker mechanism) are cached on client objects, if an info set is refused once, the server will not ask the client to compile it again. Modified: pypy/dist/pypy/tool/build/client.py ============================================================================== --- pypy/dist/pypy/tool/build/client.py (original) +++ pypy/dist/pypy/tool/build/client.py Mon Dec 11 13:46:29 2006 @@ -8,6 +8,7 @@ self.channel = channel self.sysinfo = sysinfo self.busy_on = None + self.refused = [] self.testing = testing from pypy.tool.build import ppbserver @@ -26,6 +27,8 @@ accepted = self.channel.receive() if accepted: thread.start_new_thread(self.wait_until_done, (info,)) + else: + self.refused.append(info) return accepted def wait_until_done(self, info): Modified: pypy/dist/pypy/tool/build/server.py ============================================================================== --- pypy/dist/pypy/tool/build/server.py (original) +++ pypy/dist/pypy/tool/build/server.py Mon Dec 11 13:46:29 2006 @@ -203,7 +203,8 @@ # XXX shuffle should be replaced by something smarter obviously ;) random.shuffle(clients) for client in clients: - if client.busy_on or not issubdict(info[0], client.sysinfo): + if (client.busy_on or not issubdict(info[0], client.sysinfo) or + info in client.refused): continue else: self._channel.send( Modified: pypy/dist/pypy/tool/build/test/fake.py ============================================================================== --- pypy/dist/pypy/tool/build/test/fake.py (original) +++ pypy/dist/pypy/tool/build/test/fake.py Mon Dec 11 13:46:29 2006 @@ -21,6 +21,7 @@ self.channel = FakeChannel() self.sysinfo = info self.busy_on = None + self.refused = [] def compile(self, info): for k, v in info[0].items(): Modified: pypy/dist/pypy/tool/build/test/test_client.py ============================================================================== --- pypy/dist/pypy/tool/build/test/test_client.py (original) +++ pypy/dist/pypy/tool/build/test/test_client.py Mon Dec 11 13:46:29 2006 @@ -66,4 +66,5 @@ c1c.send(False) # notifying we _don't_ 'accept' the compile accepted = c1.compile(info) assert not accepted + assert info in c1.refused From fijal at codespeak.net Mon Dec 11 13:47:35 2006 From: fijal at codespeak.net (fijal at codespeak.net) Date: Mon, 11 Dec 2006 13:47:35 +0100 (CET) Subject: [pypy-svn] r35569 - pypy/dist/pypy/translator/js/test Message-ID: <20061211124735.84B1810081@code0.codespeak.net> Author: fijal Date: Mon Dec 11 13:47:34 2006 New Revision: 35569 Modified: pypy/dist/pypy/translator/js/test/runtest.py Log: Fixed one test. Modified: pypy/dist/pypy/translator/js/test/runtest.py ============================================================================== --- pypy/dist/pypy/translator/js/test/runtest.py (original) +++ pypy/dist/pypy/translator/js/test/runtest.py Mon Dec 11 13:47:34 2006 @@ -143,7 +143,10 @@ # return self._cli_func def f(): res = fn(*args) - return str(res) + if isinstance(res, type(None)): + return None + else: + return str(res) return compile_function(f, []) def interpret(self, fn, args): From guido at codespeak.net Mon Dec 11 13:51:23 2006 From: guido at codespeak.net (guido at codespeak.net) Date: Mon, 11 Dec 2006 13:51:23 +0100 (CET) Subject: [pypy-svn] r35570 - pypy/dist/pypy/tool/build/bin Message-ID: <20061211125123.2574110082@code0.codespeak.net> Author: guido Date: Mon Dec 11 13:51:21 2006 New Revision: 35570 Modified: pypy/dist/pypy/tool/build/bin/client Log: Oops, using wrong var name. Modified: pypy/dist/pypy/tool/build/bin/client ============================================================================== --- pypy/dist/pypy/tool/build/bin/client (original) +++ pypy/dist/pypy/tool/build/bin/client Mon Dec 11 13:51:21 2006 @@ -38,7 +38,7 @@ ) sysinfo, compileinfo = data accepting = True - for checker in config.client_checkers: + for checker in buildconfig.client_checkers: if not checker(sysinfo, compileinfo): accepting = False break From mwh at codespeak.net Mon Dec 11 15:02:19 2006 From: mwh at codespeak.net (mwh at codespeak.net) Date: Mon, 11 Dec 2006 15:02:19 +0100 (CET) Subject: [pypy-svn] r35573 - pypy/dist/pypy/interpreter Message-ID: <20061211140219.3DBA81007D@code0.codespeak.net> Author: mwh Date: Mon Dec 11 15:02:17 2006 New Revision: 35573 Modified: pypy/dist/pypy/interpreter/pyopcode.py Log: oops Modified: pypy/dist/pypy/interpreter/pyopcode.py ============================================================================== --- pypy/dist/pypy/interpreter/pyopcode.py (original) +++ pypy/dist/pypy/interpreter/pyopcode.py Mon Dec 11 15:02:17 2006 @@ -183,7 +183,7 @@ # dispatch to the opcode method meth = getattr(self, opdesc.methodname) res = meth(oparg, next_instr) - if opcode == opcodedesc.CALL_FUNCTION.index: + if opdesc.index == opcodedesc.CALL_FUNCTION.index: rstack.resume_point("dispatch_call", self, co_code, next_instr, ec) # !! warning, for the annotator the next line is not # comparing an int and None - you can't do that. From arigo at codespeak.net Mon Dec 11 15:07:58 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 11 Dec 2006 15:07:58 +0100 (CET) Subject: [pypy-svn] r35574 - in pypy/dist/pypy/jit/codegen: i386/test llvm/test Message-ID: <20061211140758.1AB3E10083@code0.codespeak.net> Author: arigo Date: Mon Dec 11 15:07:54 2006 New Revision: 35574 Modified: pypy/dist/pypy/jit/codegen/i386/test/test_operation.py pypy/dist/pypy/jit/codegen/llvm/test/test_operation.py Log: Answering to eric who just left #pypy :-) Modified: pypy/dist/pypy/jit/codegen/i386/test/test_operation.py ============================================================================== --- pypy/dist/pypy/jit/codegen/i386/test/test_operation.py (original) +++ pypy/dist/pypy/jit/codegen/i386/test/test_operation.py Mon Dec 11 15:07:54 2006 @@ -8,6 +8,7 @@ from pypy.rpython.memory.lltypelayout import convert_offset_to_int from pypy.rlib.rarithmetic import r_uint from ctypes import cast, c_void_p, CFUNCTYPE, c_int +from pypy import conftest def conv(n): if not isinstance(n, int): @@ -52,6 +53,8 @@ t.buildannotator().build_types(ll_function, argtypes) t.buildrtyper().specialize() graph = graphof(t, ll_function) + if conftest.option.view: + graph.show() rgenop = self.RGenOp() self.rgenop = rgenop # keep this alive! gv_generated = graph2rgenop.compile_graph(rgenop, graph) Modified: pypy/dist/pypy/jit/codegen/llvm/test/test_operation.py ============================================================================== --- pypy/dist/pypy/jit/codegen/llvm/test/test_operation.py (original) +++ pypy/dist/pypy/jit/codegen/llvm/test/test_operation.py Mon Dec 11 15:07:54 2006 @@ -21,6 +21,13 @@ test_unsigned = skip #XXX -r_uint(n) generated op_int_sub(0,n) , why not op_uint_sub? + # -AR- for me it crashes on the 'x%y' test. The LLVM ref manual + # seems to mention only 'srem' and 'urem' instructions and + # not 'rem'. Same for 'sdiv' and 'udiv' and no 'div'. + # Strange, the translator/llvm backend seems to produce + # 'div' and 'rem' anyway... + # -AR- I see in llvm.rgenop that op_uint_invert uses an IntConst + # (should be UIntConst). test_float_arithmetic = skip #XXX bool(f - 2.0) generated op_float_sub(f,IntConst(2)) , why not FloatConst(2.0) ? @@ -28,6 +35,13 @@ # > ArgumentError: argument 1: exceptions.TypeError: int expected instead of float instance # [/mnt/hdb3/projects.eric/pypy-dist/pypy/jit/codegen/i386/test/test_operation.py:240] + # -AR- the ctypes function type need to be fixed in rgen() in + # i386.test.test_operation. For now it assumes that all args are + # c_int. The llvm.rgenop.genconst() method should have more cases + # instead of always returning IntConst for any Primitive type; + # e.g. return UIntConst for unsigned integer types, FloatConst for + # float types, and possibly things like CharConst UniCharConst etc. + # based on what T is (the same kind of checks as in kindToken()) test_char_array = skip test_char_varsize_array = skip From mwh at codespeak.net Mon Dec 11 15:14:58 2006 From: mwh at codespeak.net (mwh at codespeak.net) Date: Mon, 11 Dec 2006 15:14:58 +0100 (CET) Subject: [pypy-svn] r35575 - pypy/dist/pypy/interpreter Message-ID: <20061211141458.97FF910087@code0.codespeak.net> Author: mwh Date: Mon Dec 11 15:14:56 2006 New Revision: 35575 Modified: pypy/dist/pypy/interpreter/pyopcode.py Log: one more resume_point Modified: pypy/dist/pypy/interpreter/pyopcode.py ============================================================================== --- pypy/dist/pypy/interpreter/pyopcode.py (original) +++ pypy/dist/pypy/interpreter/pyopcode.py Mon Dec 11 15:14:56 2006 @@ -52,7 +52,9 @@ def dispatch(self, co_code, next_instr, ec): while True: try: - return self.dispatch_bytecode(co_code, next_instr, ec) + w_result = self.dispatch_bytecode(co_code, next_instr, ec) + rstack.resume_point("dispatch", self, ec, returns=w_result) + return w_result except OperationError, operr: next_instr = self.handle_operation_error(ec, operr) except Reraise: From arigo at codespeak.net Mon Dec 11 15:34:23 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 11 Dec 2006 15:34:23 +0100 (CET) Subject: [pypy-svn] r35576 - in pypy/dist/pypy: config objspace Message-ID: <20061211143423.6BA2110092@code0.codespeak.net> Author: arigo Date: Mon Dec 11 15:34:22 2006 New Revision: 35576 Added: pypy/dist/pypy/objspace/taint.py - copied, changed from r35575, pypy/dist/pypy/objspace/sand.py Removed: pypy/dist/pypy/objspace/sand.py Modified: pypy/dist/pypy/config/pypyoption.py Log: Rename this objspace sand => taint. Better matches what it does, and avoids conflict with 's' completion that used to give 'std' :-) Also restore the now-taint objspace name from pypyoption.py, where the recent config branch merge killed it by mistake. Modified: pypy/dist/pypy/config/pypyoption.py ============================================================================== --- pypy/dist/pypy/config/pypyoption.py (original) +++ pypy/dist/pypy/config/pypyoption.py Mon Dec 11 15:34:22 2006 @@ -20,7 +20,8 @@ pypy_optiondescription = OptionDescription("objspace", "Object Space Option", [ ChoiceOption("name", "Object Space name", - ["std", "flow", "logic", "thunk", "cpy", "dump"], "std", + ["std", "flow", "logic", "thunk", "cpy", "dump", "taint"], + "std", requires = { "thunk": [("objspace.geninterp", False)], "logic": [("objspace.geninterp", False), From mwh at codespeak.net Mon Dec 11 16:31:07 2006 From: mwh at codespeak.net (mwh at codespeak.net) Date: Mon, 11 Dec 2006 16:31:07 +0100 (CET) Subject: [pypy-svn] r35580 - pypy/dist/pypy/translator Message-ID: <20061211153107.4E50210070@code0.codespeak.net> Author: mwh Date: Mon Dec 11 16:31:06 2006 New Revision: 35580 Modified: pypy/dist/pypy/translator/driver.py Log: pass the config to the GenLLVM object in driver.py Modified: pypy/dist/pypy/translator/driver.py ============================================================================== --- pypy/dist/pypy/translator/driver.py (original) +++ pypy/dist/pypy/translator/driver.py Mon Dec 11 16:31:06 2006 @@ -473,7 +473,7 @@ # XXX Need more options for policies/llvm-backendoptions here? self.llvmgen = genllvm.GenLLVM(translator, self.config.translation.gc, - self.standalone) + self.standalone, config=self.config) llvm_filename = self.llvmgen.gen_llvm_source(self.entry_point) self.log.info("written: %s" % (llvm_filename,)) From ericvrp at codespeak.net Mon Dec 11 16:50:54 2006 From: ericvrp at codespeak.net (ericvrp at codespeak.net) Date: Mon, 11 Dec 2006 16:50:54 +0100 (CET) Subject: [pypy-svn] r35582 - in pypy/dist/pypy/jit/codegen/llvm: . test Message-ID: <20061211155054.0C2FF10093@code0.codespeak.net> Author: ericvrp Date: Mon Dec 11 16:50:53 2006 New Revision: 35582 Modified: pypy/dist/pypy/jit/codegen/llvm/rgenop.py pypy/dist/pypy/jit/codegen/llvm/test/test_operation.py Log: Extended genconst() for Char,UniChar,Unsigned and Float. test_unsigned passes now, test_float_arithmetic still disabled. Continuing the svn chat feature ;) Modified: pypy/dist/pypy/jit/codegen/llvm/rgenop.py ============================================================================== --- pypy/dist/pypy/jit/codegen/llvm/rgenop.py (original) +++ pypy/dist/pypy/jit/codegen/llvm/rgenop.py Mon Dec 11 16:50:53 2006 @@ -38,8 +38,8 @@ return '%%v%d' % (self.n,) -class IntConst(GenConst): - type = 'int' +class GenericConst(GenConst): + #type = 'generic' def __init__(self, value): self.value = value @@ -60,6 +60,30 @@ return lltype.cast_primitive(T, self.value) +class BoolConst(GenericConst): + type = 'int' + + +class CharConst(GenericConst): + type = 'ubyte' + + +class UniCharConst(GenericConst): + type = 'int' + + +class IntConst(GenericConst): + type = 'int' + + +class UIntConst(GenericConst): + type = 'uint' + + +class FloatConst(GenericConst): + type = 'float' + + class AddrConst(GenConst): type = 'int*' @@ -343,7 +367,7 @@ def op_int_neg(self, gv_x): return self._rgenop2_generic('sub', IntConst(0), gv_x) def op_int_invert(self, gv_x): return self._rgenop2_generic('xor', gv_x, IntConst(-1)) - def op_uint_invert(self, gv_x): return self._rgenop2_generic('xor', gv_x, IntConst((1<<32)-1)) + def op_uint_invert(self, gv_x): return self._rgenop2_generic('xor', gv_x, UIntConst((1<<32)-1)) def op_int_abs(self, gv_x): gv_comp = Var('bool') @@ -460,6 +484,10 @@ def op_float_is_true(self, gv_x): return self._is_true(gv_x, '0.0') + def genop_malloc_varsize(self, varsizealloctoken, gv_size): + gv_result = Var('sbyte') #XXX TODO + return gv_result + def genop_call(self, sigtoken, gv_fnptr, args_gv): log('%s Builder.genop_call %s,%s,%s' % ( self.block.label, sigtoken, gv_fnptr, [v.operand() for v in args_gv])) @@ -556,6 +584,14 @@ T = lltype.typeOf(llvalue) if T is llmemory.Address: return AddrConst(llvalue) + elif T is lltype.Bool: + return BoolConst(lltype.cast_primitive(lltype.Bool, llvalue)) + elif T is lltype.Char: + return CharConst(lltype.cast_primitive(lltype.Char, llvalue)) + elif T is lltype.Unsigned: + return UIntConst(lltype.cast_primitive(lltype.Unsigned, 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): @@ -601,14 +637,14 @@ @staticmethod @specialize.memo() def varsizeAllocToken(T): - XXX + #XXX TODO if isinstance(T, lltype.Array): - return RI386GenOp.arrayToken(T) + return RLLVMGenOp.arrayToken(T) else: # var-sized structs arrayfield = T._arrayfld ARRAYFIELD = getattr(T, arrayfield) - arraytoken = RI386GenOp.arrayToken(ARRAYFIELD) + arraytoken = RLLVMGenOp.arrayToken(ARRAYFIELD) length_offset, items_offset, item_size = arraytoken arrayfield_offset = llmemory.offsetof(T, arrayfield) return (arrayfield_offset+length_offset, @@ -618,7 +654,7 @@ @staticmethod @specialize.memo() def arrayToken(A): - XXX + #XXX TODO return (llmemory.ArrayLengthOffset(A), llmemory.ArrayItemsOffset(A), llmemory.ItemOffset(A.OF)) Modified: pypy/dist/pypy/jit/codegen/llvm/test/test_operation.py ============================================================================== --- pypy/dist/pypy/jit/codegen/llvm/test/test_operation.py (original) +++ pypy/dist/pypy/jit/codegen/llvm/test/test_operation.py Mon Dec 11 16:50:53 2006 @@ -19,15 +19,17 @@ def skip(self): py.test.skip('WIP') - test_unsigned = skip + #test_unsigned = skip #XXX -r_uint(n) generated op_int_sub(0,n) , why not op_uint_sub? # -AR- for me it crashes on the 'x%y' test. The LLVM ref manual # seems to mention only 'srem' and 'urem' instructions and # not 'rem'. Same for 'sdiv' and 'udiv' and no 'div'. # Strange, the translator/llvm backend seems to produce # 'div' and 'rem' anyway... + # -ER- the langref on llvm.org seems to be for the upcoming llvm version 2.0 # -AR- I see in llvm.rgenop that op_uint_invert uses an IntConst # (should be UIntConst). + # -ER- indeed test_float_arithmetic = skip #XXX bool(f - 2.0) generated op_float_sub(f,IntConst(2)) , why not FloatConst(2.0) ? @@ -42,6 +44,7 @@ # e.g. return UIntConst for unsigned integer types, FloatConst for # float types, and possibly things like CharConst UniCharConst etc. # based on what T is (the same kind of checks as in kindToken()) + # -ER- extended genconst() test_char_array = skip test_char_varsize_array = skip From arigo at codespeak.net Mon Dec 11 17:06:41 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 11 Dec 2006 17:06:41 +0100 (CET) Subject: [pypy-svn] r35583 - pypy/dist/pypy/module/__builtin__/test Message-ID: <20061211160641.D74591009C@code0.codespeak.net> Author: arigo Date: Mon Dec 11 17:06:40 2006 New Revision: 35583 Modified: pypy/dist/pypy/module/__builtin__/test/test_builtin.py Log: (pedronis, arigo) Detect if we're running on top of a Python with broken dict lookup semantics (eating all exceptions) and skip a test that this fact makes fragile. (Works with 'pypy-c -A', or with a patched CPython.) Modified: pypy/dist/pypy/module/__builtin__/test/test_builtin.py ============================================================================== --- pypy/dist/pypy/module/__builtin__/test/test_builtin.py (original) +++ pypy/dist/pypy/module/__builtin__/test/test_builtin.py Mon Dec 11 17:06:40 2006 @@ -2,6 +2,20 @@ class AppTestBuiltinApp: + def setup_class(cls): + class X(object): + def __eq__(self, other): + raise OverflowError + def __hash__(self): + return 42 + d = {X(): 5} + try: + d[X()] + except OverflowError: + cls.w_sane_lookup = cls.space.wrap(True) + except KeyError: + cls.w_sane_lookup = cls.space.wrap(False) + def test_import(self): m = __import__('pprint') assert m.pformat({}) == '{}' @@ -268,6 +282,8 @@ raises(RuntimeError, cmp, c1, c2) def test_cmp_cyclic(self): + if not self.sane_lookup: + skip("underlying Python implementation has insane dict lookup") a = []; a.append(a) b = []; b.append(b) from UserList import UserList From mwh at codespeak.net Mon Dec 11 18:21:39 2006 From: mwh at codespeak.net (mwh at codespeak.net) Date: Mon, 11 Dec 2006 18:21:39 +0100 (CET) Subject: [pypy-svn] r35585 - pypy/dist/pypy/module/_stackless Message-ID: <20061211172139.41EB51008E@code0.codespeak.net> Author: mwh Date: Mon Dec 11 18:21:38 2006 New Revision: 35585 Modified: pypy/dist/pypy/module/_stackless/coroutine.py Log: redo the resume_state_creates() in frame_reconstruction. compiles, don't know if it works yet :-) Modified: pypy/dist/pypy/module/_stackless/coroutine.py ============================================================================== --- pypy/dist/pypy/module/_stackless/coroutine.py (original) +++ pypy/dist/pypy/module/_stackless/coroutine.py Mon Dec 11 18:21:38 2006 @@ -209,17 +209,15 @@ chain = appthunk_frame for frame in self.subctx.framestack.items: assert isinstance(frame, PyFrame) - # rstack.resume_point("evalframe", self, executioncontext, returns=result) - evalframe_frame = resume_state_create(chain, "evalframe", frame, ec) - # rstack.resume_point("eval", self, executioncontext) - eval_frame = resume_state_create(evalframe_frame, "eval", frame, ec) + evalframe_frame = resume_state_create(chain, "execute_frame", frame, ec) + eval_frame = resume_state_create(evalframe_frame, "dispatch", frame, ec) # rstack.resume_point("dispatch_call", self, code, ec) code = frame.getcode().co_code - dispatch_call_frame = resume_state_create(eval_frame, "dispatch_call", frame, code, ec) instr = frame.last_instr opcode = ord(code[instr]) assert opcode == pythonopcode.opmap['CALL_FUNCTION'] instr += 1 + dispatch_call_frame = resume_state_create(eval_frame, "dispatch_call", frame, ec, code, instr+3) oparg = ord(code[instr]) | ord(code[instr + 1]) << 8 if (oparg >> 8) & 0xff == 0: # Only positional arguments From guido at codespeak.net Mon Dec 11 20:39:29 2006 From: guido at codespeak.net (guido at codespeak.net) Date: Mon, 11 Dec 2006 20:39:29 +0100 (CET) Subject: [pypy-svn] r35597 - in pypy/dist/pypy/tool/build: . bin test Message-ID: <20061211193929.405371007B@code0.codespeak.net> Author: guido Date: Mon Dec 11 20:39:17 2006 New Revision: 35597 Modified: pypy/dist/pypy/tool/build/bin/client pypy/dist/pypy/tool/build/bin/startcompile pypy/dist/pypy/tool/build/client.py pypy/dist/pypy/tool/build/config.py pypy/dist/pypy/tool/build/server.py pypy/dist/pypy/tool/build/test/test_client.py pypy/dist/pypy/tool/build/test/test_pypybuilder.py pypy/dist/pypy/tool/build/test/test_server.py Log: Capturing stdout/stderr and sending to the server when done, cleaning up build paths that aren't 'done' (no log written to it) on startup. Modified: pypy/dist/pypy/tool/build/bin/client ============================================================================== --- pypy/dist/pypy/tool/build/bin/client (original) +++ pypy/dist/pypy/tool/build/bin/client Mon Dec 11 20:39:17 2006 @@ -6,7 +6,7 @@ from pypy.tool.build import config as buildconfig from py.execnet import SshGateway, PopenGateway -from pypy.tool.build.client import init, zip_result +from pypy.tool.build.client import init, zip_result, OutputBuffer from pypy.config.config import to_optparse, Config from pypy.config import pypyoption @@ -52,14 +52,24 @@ config = pypyoption.get_pypy_config() config.override(compileinfo) - # XXX compile here... - driver = TranslationDriver.from_targetspec( - targetpypystandalone.__dict__, config=config, - default_goal='compile') - driver.proceed(['compile']) + buffer = OutputBuffer(sys.__stderr__) + sys.stdout = buffer + sys.stderr = buffer + try: + driver = TranslationDriver.from_targetspec( + targetpypystandalone.__dict__, config=config, + default_goal='compile') + driver.proceed(['compile']) + finally: + sys.stdout = sys.__stdout__ + sys.stderr = sys.__stderr__ + # send over zip data, end with a None zip_result(udir, channel) + # send over logs + channel.send(buffer.getvalue()) + print 'done with compilation, waiting for next' except EOFError: sys.exit() Modified: pypy/dist/pypy/tool/build/bin/startcompile ============================================================================== --- pypy/dist/pypy/tool/build/bin/startcompile (original) +++ pypy/dist/pypy/tool/build/bin/startcompile Mon Dec 11 20:39:17 2006 @@ -41,8 +41,8 @@ from pypy.tool.build import execnetconference conference = execnetconference.conference(gw, port, False) - channel = conference.remote_exec(initcode % (path, email, - sysinfo, compileinfo)) + channel = conference.remote_exec(initcode % (path, email, sysinfo, + compileinfo)) return channel if __name__ == '__main__': @@ -66,8 +66,8 @@ gw = PopenGateway() else: gw = SshGateway(config.server) - channel = init(gw, sysinfo, compileinfo, config.path, args[0], - port=config.port) + channel = init(gw, sysinfo, compileinfo, config.path, args[0], + port=config.port) data = channel.receive() if type(data) == str: print data @@ -79,7 +79,7 @@ ispath, data = data if ispath: print ('a suitable result is already available, you can find it ' - 'at "%s"' % (data,)) + 'at "%s"' % (data,)) else: print data print 'you will be mailed once it\'s ready' Modified: pypy/dist/pypy/tool/build/client.py ============================================================================== --- pypy/dist/pypy/tool/build/client.py (original) +++ pypy/dist/pypy/tool/build/client.py Mon Dec 11 20:39:17 2006 @@ -1,7 +1,7 @@ import thread import py from zipfile import ZipFile - +from cStringIO import StringIO class PPBClient(object): def __init__(self, channel, sysinfo, testing=False): @@ -22,10 +22,10 @@ def compile(self, info): """send a compile job to the client side""" - self.busy_on = info self.channel.send(info) accepted = self.channel.receive() if accepted: + self.busy_on = info thread.start_new_thread(self.wait_until_done, (info,)) else: self.refused.append(info) @@ -44,12 +44,15 @@ except EOFError: # stop compilation, client has disconnected return + # end of data is marked by sending a None if chunk is None: break fp.write(chunk) finally: fp.close() - + # write the log (process stdout/stderr) to the buildpath + buildpath.log = self.channel.receive() + self.server.compilation_done(info, buildpath) self.busy_on = None @@ -123,3 +126,17 @@ print exc continue zip.close() + +class OutputBuffer(object): + def __init__(self, print_channel=None): + self.print_channel = print_channel + self.buffer = StringIO() + + def write(self, s): + self.buffer.write(s) + if self.print_channel: + self.print_channel.write(s) + + def getvalue(self): + return self.buffer.getvalue() + Modified: pypy/dist/pypy/tool/build/config.py ============================================================================== --- pypy/dist/pypy/tool/build/config.py (original) +++ pypy/dist/pypy/tool/build/config.py Mon Dec 11 20:39:17 2006 @@ -5,6 +5,7 @@ # general settings, used by both server and client server = 'localhost' port = 12321 +testport = 32123 path = [str(packageparent)] # configuration of options for client and startcompile Modified: pypy/dist/pypy/tool/build/server.py ============================================================================== --- pypy/dist/pypy/tool/build/server.py (original) +++ pypy/dist/pypy/tool/build/server.py Mon Dec 11 20:39:17 2006 @@ -132,6 +132,21 @@ zipfile = property(_zipfile, _set_zipfile) + def _log(self): + log = self.join('log') + if not log.check(): + return '' + return log.read() + + def _set_log(self, data): + self.join('log').write(data) + + log = property(_log, _set_log) + + def _done(self): + return not not self.log + done = property(_done) + class PPBServer(object): retry_interval = 10 @@ -146,8 +161,13 @@ self._buildpath = py.path.local(builddir) self._clients = [] - info_to_path = [(p.info, str(p)) for p in - self._get_buildpaths(builddir)] + info_to_path = [] + for bp in self._get_buildpaths(builddir): + if bp.done: + info_to_path.append((bp.info, str(bp))) + else: + # throw away half-done builds... + bp.remove() self._requeststorage = RequestStorage(info_to_path) self._queued = [] Modified: pypy/dist/pypy/tool/build/test/test_client.py ============================================================================== --- pypy/dist/pypy/tool/build/test/test_client.py (original) +++ pypy/dist/pypy/tool/build/test/test_client.py Mon Dec 11 20:39:17 2006 @@ -2,6 +2,7 @@ from pypy.tool.build import client import py import time +import sys from fake import FakeChannel, FakeServer class ClientForTests(client.PPBClient): @@ -31,8 +32,10 @@ assert accepted ret = c1.channel.receive() assert ret == info # this was still in the buffer + assert c1.busy_on == info c1.channel.send('foo bar') c1.channel.send(None) + c1.channel.send('log') # meanwhile the client starts a thread that waits until there's data # available on its own channel, with our FakeChannel it has data rightaway, @@ -44,6 +47,7 @@ assert done[0] == info assert done[1] == (temp / 'build-0') + assert temp.join('build-0/log').read() == 'log' def test_channelwrapper(): class FakeChannel(object): @@ -67,4 +71,22 @@ accepted = c1.compile(info) assert not accepted assert info in c1.refused + assert c1.busy_on == None + +def test_output_buffer(): + b = client.OutputBuffer() + sys.stdout = b + try: + print 'foo' + finally: + sys.stdout = sys.__stdout__ + assert b.getvalue() == 'foo\n' + s = py.std.StringIO.StringIO() + b = client.OutputBuffer(s) + sys.stdout = b + try: + print 'bar' + finally: + sys.stdout = sys.__stdout__ + assert b.getvalue() == s.getvalue() == 'bar\n' Modified: pypy/dist/pypy/tool/build/test/test_pypybuilder.py ============================================================================== --- pypy/dist/pypy/tool/build/test/test_pypybuilder.py (original) +++ pypy/dist/pypy/tool/build/test/test_pypybuilder.py Mon Dec 11 20:39:17 2006 @@ -28,7 +28,7 @@ # first initialize a server sgw = py.execnet.PopenGateway() temppath = py.test.ensuretemp('pypybuilder-functional') - sc = server.init(sgw, port=config.port, path=config.testpath, + sc = server.init(sgw, port=config.testport, path=config.testpath, buildpath=str(temppath)) # give the server some time to wake up @@ -37,12 +37,14 @@ # then two clients, both with different system info sysconfig1 = _get_sysconfig() cgw1 = py.execnet.PopenGateway() - cc1 = client.init(cgw1, sysconfig1, port=config.port, testing=True) + cc1 = client.init(cgw1, sysconfig1, port=config.testport, testing=True) + cc1.receive() # welcome message sysconfig2 = _get_sysconfig() sysconfig2.foo = 2 cgw2 = py.execnet.PopenGateway() - cc2 = client.init(cgw2, sysconfig2, port=config.port, testing=True) + cc2 = client.init(cgw2, sysconfig2, port=config.testport, testing=True) + cc2.receive() # welcome message # give the clients some time to register themselves py.std.time.sleep(SLEEP_INTERVAL) @@ -57,14 +59,11 @@ channel.close() """ compgw = py.execnet.PopenGateway() - compconf = execnetconference.conference(compgw, config.port) - - # clients normally respond with a boolean on a compilation request... to - # allow the code to continue, already put some Trues (meaning 'I accept - # the job') in the buffers - cc1.send(True) - cc2.send(True) + compconf = execnetconference.conference(compgw, config.testport) + # we're going to have to closely mimic the bin/client script to avoid + # freezes (from the app waiting for input) + # this one should fail because there's no client found for foo = 3 compc = compconf.remote_exec(code % (config.testpath, 'foo1 at bar.com', {'foo': 3})) @@ -80,10 +79,14 @@ compc = compconf.remote_exec(code % (config.testpath, 'foo2 at bar.com', {'foo': 1})) + # client 1 will now send a True to the server to tell it wants to compile + cc1.send(True) + # and another one py.std.time.sleep(SLEEP_INTERVAL) ret = compc.receive() + print repr(ret) assert not ret[0] assert ret[1].find('found a suitable client') > -1 @@ -91,7 +94,6 @@ py.std.time.sleep(SLEEP_INTERVAL) # client 1 should by now have received the info to build for - cc1.receive() # 'welcome' ret = cc1.receive() assert ret == ({'foo': 1}, {}) @@ -102,7 +104,7 @@ sysconfig3 = _get_sysconfig() sysconfig3.foo = 3 cgw3 = py.execnet.PopenGateway() - cc3 = client.init(cgw3, sysconfig3, port=config.port, testing=True) + cc3 = client.init(cgw3, sysconfig3, port=config.testport, testing=True) # add True to the buffer just like we did for channels 1 and 2 cc3.send(True) @@ -124,9 +126,10 @@ channel.close() """ compgw2 = py.execnet.PopenGateway() - compconf2 = execnetconference.conference(compgw2, config.port) + compconf2 = execnetconference.conference(compgw2, config.testport) compc2 = compconf2.remote_exec(code % (config.testpath, SLEEP_INTERVAL)) + cc2.send(True) # we check whether all emails are now sent, since after adding the third # client, and calling _try_queued(), both jobs should have been processed Modified: pypy/dist/pypy/tool/build/test/test_server.py ============================================================================== --- pypy/dist/pypy/tool/build/test/test_server.py (original) +++ pypy/dist/pypy/tool/build/test/test_server.py Mon Dec 11 20:39:17 2006 @@ -94,13 +94,13 @@ def test_buildpath(): tempdir = py.test.ensuretemp('pypybuilder-buildpath') # grmbl... local.__new__ checks for class equality :( - bp = BuildPath(str(tempdir / 'test1')) + bp = BuildPath(str(tempdir / 'test1')) assert not bp.check() assert bp.info == ({}, {}) bp.info = ({'foo': 1, 'bar': [1,2]}, {'baz': 1}) assert bp.info == ({'foo': 1, 'bar': [1,2]}, {'baz': 1}) - assert (sorted((bp / 'system_info.txt').readlines()) == + assert (sorted((bp / 'system_info.txt').readlines()) == ['bar: [1, 2]\n', 'foo: 1\n']) assert isinstance(bp.zipfile, py.path.local) @@ -138,3 +138,15 @@ path2.remove() finally: path1.remove() + +def test_cleanup_old_builds(): + temppath = py.test.ensuretemp('cleanup_old_builds') + bp1 = server.BuildPath(temppath.join('bp1')) + bp1.ensure(dir=True) + bp2 = server.BuildPath(temppath.join('bp2')) + bp2.ensure(dir=True) + bp2.log = 'log' + svr = server.PPBServer('test', FakeChannel(), str(temppath)) + assert not bp1.check() + assert bp2.check() + From arigo at codespeak.net Mon Dec 11 22:56:10 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 11 Dec 2006 22:56:10 +0100 (CET) Subject: [pypy-svn] r35600 - pypy/dist/pypy/jit/codegen/i386 Message-ID: <20061211215610.058641008F@code0.codespeak.net> Author: arigo Date: Mon Dec 11 22:56:08 2006 New Revision: 35600 Modified: pypy/dist/pypy/jit/codegen/i386/codebuf_posix.py Log: (pedronis, arigo) The mmap error value is (void*) -1, not NULL. Modified: pypy/dist/pypy/jit/codegen/i386/codebuf_posix.py ============================================================================== --- pypy/dist/pypy/jit/codegen/i386/codebuf_posix.py (original) +++ pypy/dist/pypy/jit/codegen/i386/codebuf_posix.py Mon Dec 11 22:56:08 2006 @@ -42,7 +42,7 @@ flags = MAP_PRIVATE | MAP_ANONYMOUS prot = PROT_EXEC | PROT_READ | PROT_WRITE res = mmap_(cast(c_void_p(hint.pos), PTR), map_size, prot, flags, -1, 0) - if not res: + if cast(res, c_void_p).value == -1: raise MemoryError hint.pos += map_size return res From arigo at codespeak.net Mon Dec 11 22:56:42 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 11 Dec 2006 22:56:42 +0100 (CET) Subject: [pypy-svn] r35601 - pypy/dist/pypy/jit/codegen Message-ID: <20061211215642.014B710092@code0.codespeak.net> Author: arigo Date: Mon Dec 11 22:56:40 2006 New Revision: 35601 Modified: pypy/dist/pypy/jit/codegen/detect_cpu.py Log: (pedronis, arigo) Trying to work around uname pretending we're on a x86_64 when we're really running in 32-bit compatibility mode. Modified: pypy/dist/pypy/jit/codegen/detect_cpu.py ============================================================================== --- pypy/dist/pypy/jit/codegen/detect_cpu.py (original) +++ pypy/dist/pypy/jit/codegen/detect_cpu.py Mon Dec 11 22:56:40 2006 @@ -19,6 +19,8 @@ mach = os.popen('uname -m', 'r').read().strip() if not mach: raise ProcessorAutodetectError, "cannot run 'uname -m'" + if mach == 'x86_64' and sys.maxint == 2147483647: + mach = 'x86' # it's a 64-bit processor but in 32-bits mode, maybe try: return {'i386': 'i386', 'i486': 'i386', From arigo at codespeak.net Mon Dec 11 22:57:47 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 11 Dec 2006 22:57:47 +0100 (CET) Subject: [pypy-svn] r35602 - pypy/dist/pypy/jit/codegen/i386/test Message-ID: <20061211215747.5501010090@code0.codespeak.net> Author: arigo Date: Mon Dec 11 22:57:46 2006 New Revision: 35602 Modified: pypy/dist/pypy/jit/codegen/i386/test/test_genc_ts.py Log: Yet another place where the config refactoring didn't go. 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 Mon Dec 11 22:57:46 2006 @@ -96,7 +96,7 @@ annhelper.finish() t = self.rtyper.annotator.translator t.config.translation.gc = 'boehm' - cbuilder = CStandaloneBuilder(t, ll_main) + cbuilder = CStandaloneBuilder(t, ll_main, config=t.config) cbuilder.generate_source() cbuilder.compile() self.main_cbuilder= cbuilder From arigo at codespeak.net Mon Dec 11 23:02:02 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 11 Dec 2006 23:02:02 +0100 (CET) Subject: [pypy-svn] r35603 - in pypy/dist/pypy/jit/codegen/i386: . test Message-ID: <20061211220202.C91221009A@code0.codespeak.net> Author: arigo Date: Mon Dec 11 23:02:01 2006 New Revision: 35603 Modified: pypy/dist/pypy/jit/codegen/i386/rgenop.py pypy/dist/pypy/jit/codegen/i386/test/test_genc_ts.py Log: (pedronis, arigo) A sanity check that all machine code blocks are properly closed. 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 Mon Dec 11 23:02:01 2006 @@ -894,6 +894,7 @@ def __init__(self): self.mcs = [] # machine code blocks where no-one is currently writing self.keepalive_gc_refs = [] + self.total_code_blocks = 0 def open_mc(self): if self.mcs: @@ -901,6 +902,7 @@ return self.mcs.pop() else: # XXX supposed infinite for now + self.total_code_blocks += 1 return self.MachineCodeBlock(self.MC_SIZE) def close_mc(self, mc): @@ -909,6 +911,9 @@ # want the generated code to stay around :-) self.mcs.append(mc) + def check_no_open_mc(self): + assert len(self.mcs) == self.total_code_blocks + def openbuilder(self, stackdepth): return Builder(self, self.open_mc(), stackdepth) 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 Mon Dec 11 23:02:01 2006 @@ -88,6 +88,7 @@ if bench.stop(): break os.write(1, convert_result(res) + '\n') + rgenop.check_no_open_mc() keepalive_until_here(rgenop) # to keep the code blocks alive return 0 From fijal at codespeak.net Mon Dec 11 23:21:20 2006 From: fijal at codespeak.net (fijal at codespeak.net) Date: Mon, 11 Dec 2006 23:21:20 +0100 (CET) Subject: [pypy-svn] r35604 - pypy/dist/pypy/tool/pytest Message-ID: <20061211222120.1478B10078@code0.codespeak.net> Author: fijal Date: Mon Dec 11 23:21:18 2006 New Revision: 35604 Modified: pypy/dist/pypy/tool/pytest/appsupport.py Log: Rewritten parts of the file into more space-operation style (to make it work under distributed proxy and such), please complain if something does not work. Modified: pypy/dist/pypy/tool/pytest/appsupport.py ============================================================================== --- pypy/dist/pypy/tool/pytest/appsupport.py (original) +++ pypy/dist/pypy/tool/pytest/appsupport.py Mon Dec 11 23:21:18 2006 @@ -7,14 +7,32 @@ # ____________________________________________________________ +class AppCode(object): + def __init__(self, space, pycode): + self.code = space.unwrap(space.getattr(pycode, space.wrap('co_code'))) + self.w_file = space.getattr(pycode, space.wrap('co_filename')) + self.firstlineno = space.unwrap(space.getattr(pycode, space.wrap('co_firstlineno'))) + #try: + # self.path = space.unwrap(space.getattr(self.w_file, space.wrap('__path__'))) + #except OperationError: + # self.path = space.unwrap(space.getattr( + self.path = py.path.local(space.str_w(self.w_file)) + + def fullsource(self): + return py.code.Source(self.path.read(mode="rU")) + fullsource = property(fullsource, None, None, "Full source of AppCode") + class AppFrame(py.code.Frame): - def __init__(self, pyframe): - self.code = py.code.Code(pyframe.pycode) - self.lineno = pyframe.get_last_lineno() - 1 - self.space = pyframe.space - self.w_globals = pyframe.w_globals - self.w_locals = pyframe.getdictscope() + def __init__(self, space, pyframe): + self.code = AppCode(space, \ + space.unwrap(space.getattr(pyframe, space.wrap('f_code')))) + #self.code = py.code.Code(pyframe.pycode) + self.lineno = space.unwrap(space.getattr(pyframe, space.wrap('f_lineno'))) - 1 + #pyframe.get_last_lineno() - 1 + self.space = space + self.w_globals = space.getattr(pyframe, space.wrap('f_globals')) + self.w_locals = space.getattr(pyframe, space.wrap('f_locals')) self.f_locals = self.w_locals # for py.test's recursion detection def eval(self, code, **vars): @@ -41,7 +59,7 @@ def __init__(self, space, operr): self.space = space self.operr = operr - self.traceback = AppTraceback(self.operr.application_traceback) + self.traceback = AppTraceback(space, self.operr.application_traceback) def exconly(self, tryshort=True): return '(application-level) ' + self.operr.errorstr(self.space) @@ -64,9 +82,9 @@ class AppTracebackEntry(py.code.Traceback.Entry): exprinfo = None - def __init__(self, tb): - self.frame = AppFrame(tb.frame) - self.lineno = tb.lineno - 1 + def __init__(self, space, tb): + self.frame = AppFrame(space, space.getattr(tb, space.wrap('tb_frame'))) + self.lineno = space.unwrap(space.getattr(tb, space.wrap('tb_lineno'))) - 1 def reinterpret(self): # XXX we need to solve a general problem: how to prevent @@ -81,13 +99,13 @@ class AppTraceback(py.code.Traceback): Entry = AppTracebackEntry - def __init__(self, apptb): + def __init__(self, space, apptb): l = [] - while apptb is not None: - l.append(self.Entry(apptb)) - apptb = apptb.next - list.__init__(self, l) - + while apptb is not space.w_None: + l.append(self.Entry(space, apptb)) + apptb = space.getattr(apptb, space.wrap('tb_next')) + list.__init__(self, l) + # ____________________________________________________________ def build_pytest_assertion(space): @@ -108,7 +126,7 @@ w_msg = args_w[0] else: frame = framestack.top(0) - runner = AppFrame(frame) + runner = AppFrame(space, frame) try: source = runner.statement source = str(source).strip() From arigo at codespeak.net Mon Dec 11 23:33:27 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 11 Dec 2006 23:33:27 +0100 (CET) Subject: [pypy-svn] r35605 - pypy/dist/pypy/jit/codegen/i386/test Message-ID: <20061211223327.C26101007D@code0.codespeak.net> Author: arigo Date: Mon Dec 11 23:33:26 2006 New Revision: 35605 Modified: pypy/dist/pypy/jit/codegen/i386/test/test_genc_portal.py Log: Yet another one of those... Modified: pypy/dist/pypy/jit/codegen/i386/test/test_genc_portal.py ============================================================================== --- pypy/dist/pypy/jit/codegen/i386/test/test_genc_portal.py (original) +++ pypy/dist/pypy/jit/codegen/i386/test/test_genc_portal.py Mon Dec 11 23:33:26 2006 @@ -44,7 +44,7 @@ annhelper.finish() t = self.rtyper.annotator.translator t.config.translation.gc = 'boehm' - self.cbuilder = CStandaloneBuilder(t, ll_main) + self.cbuilder = CStandaloneBuilder(t, ll_main, config=t.config) self.cbuilder.generate_source() self.cbuilder.compile() From arigo at codespeak.net Mon Dec 11 23:34:00 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 11 Dec 2006 23:34:00 +0100 (CET) Subject: [pypy-svn] r35606 - pypy/dist/pypy/jit Message-ID: <20061211223400.62FCF10087@code0.codespeak.net> Author: arigo Date: Mon Dec 11 23:33:59 2006 New Revision: 35606 Modified: pypy/dist/pypy/jit/TODO.txt Log: (pedronis, arigo) Updated TODO list. Modified: pypy/dist/pypy/jit/TODO.txt ============================================================================== --- pypy/dist/pypy/jit/TODO.txt (original) +++ pypy/dist/pypy/jit/TODO.txt Mon Dec 11 23:33:59 2006 @@ -16,6 +16,8 @@ beginning of the portal, but concretely implemented in the portal entry +- minimize the number of concurrently open machinecodeblocks in the + machine code backends - make backend opts usable on the interp+timeshifted interp graph forest @@ -41,3 +43,6 @@ initial 0 of RPython list iterators - pyopcode.compare_dispatch_table => switch statement + +- share code between the machine code backends (MachineCodeBlock, + possibly register allocation) From fijal at codespeak.net Mon Dec 11 23:47:06 2006 From: fijal at codespeak.net (fijal at codespeak.net) Date: Mon, 11 Dec 2006 23:47:06 +0100 (CET) Subject: [pypy-svn] r35607 - pypy/dist/pypy/objspace/std/test Message-ID: <20061211224706.D97A11009F@code0.codespeak.net> Author: fijal Date: Mon Dec 11 23:47:05 2006 New Revision: 35607 Modified: pypy/dist/pypy/objspace/std/test/test_proxy_internals.py Log: Added a test Modified: pypy/dist/pypy/objspace/std/test/test_proxy_internals.py ============================================================================== --- pypy/dist/pypy/objspace/std/test/test_proxy_internals.py (original) +++ pypy/dist/pypy/objspace/std/test/test_proxy_internals.py Mon Dec 11 23:47:05 2006 @@ -31,6 +31,18 @@ tb = self.get_proxy(e[2]) assert tb.tb_frame is e[2].tb_frame + + def test_traceback_catch(self): + try: + try: + 1/0 + except ZeroDivisionError, e: + ex = self.get_proxy(e) + raise ex + except ZeroDivisionError: + pass + else: + raise AssertionError("Did not raise") def test_traceback_reraise(self): #skip("Not implemented yet") From fijal at codespeak.net Tue Dec 12 00:04:55 2006 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 12 Dec 2006 00:04:55 +0100 (CET) Subject: [pypy-svn] r35609 - in pypy/dist/pypy/lib: distributed test2 Message-ID: <20061211230455.182051007A@code0.codespeak.net> Author: fijal Date: Tue Dec 12 00:04:41 2006 New Revision: 35609 Modified: pypy/dist/pypy/lib/distributed/__init__.py pypy/dist/pypy/lib/distributed/objkeeper.py pypy/dist/pypy/lib/distributed/protocol.py pypy/dist/pypy/lib/test2/test_distributed.py Log: Added some support for exceptions (but tracebacks has some garbage inside - also due to old greenlets interface) Modified: pypy/dist/pypy/lib/distributed/__init__.py ============================================================================== --- pypy/dist/pypy/lib/distributed/__init__.py (original) +++ pypy/dist/pypy/lib/distributed/__init__.py Tue Dec 12 00:04:41 2006 @@ -1,2 +1,2 @@ -from protocol import RemoteProtocol, test_env +from protocol import RemoteProtocol, test_env, remote_loop Modified: pypy/dist/pypy/lib/distributed/objkeeper.py ============================================================================== --- pypy/dist/pypy/lib/distributed/objkeeper.py (original) +++ pypy/dist/pypy/lib/distributed/objkeeper.py Tue Dec 12 00:04:41 2006 @@ -2,6 +2,15 @@ """ objkeeper - Storage for remoteprotocol """ +# XXX jeez + +import sys +try: + 1/0 +except: + _, _, tb = sys.exc_info() + GetSetDescriptor = type(type(tb).tb_frame) + class ObjKeeper(object): def __init__(self, exported_names = {}): self.exported_objects = [] # list of object that we've exported outside @@ -16,11 +25,22 @@ self.exported_objects.append(obj) return len(self.exported_objects) - 1 + def ignore(self, key, value): + #key not in ('__dict__', '__weakref__', '__class__', '__new__', + # '__base__', '__flags__', '__mro__', '__bases__')] + if key in ('__dict__', '__weakref__', '__class__', '__new__'): + return True + if isinstance(value, GetSetDescriptor): + return True + return False + def register_type(self, protocol, tp): try: return self.exported_types[tp] except KeyError: print "Registering type %s as %s" % (tp, self.exported_types_id) + if str(tp).find('getset') != -1: + import pdb;pdb.set_trace() self.exported_types[tp] = self.exported_types_id tp_id = self.exported_types_id self.exported_types_id += 1 @@ -28,8 +48,7 @@ # XXX: We don't support inheritance here, nor recursive types # shall we??? _dict = dict([(key, protocol.wrap(getattr(tp, key))) for key in dir(tp) - if key not in ('__dict__', '__weakref__', '__class__', '__new__', - '__base__', '__flags__', '__mro__', '__bases__')]) + if not self.ignore(key, getattr(tp, key))]) protocol.send(("type_reg", (tp_id, tp.__name__, _dict))) return tp_id Modified: pypy/dist/pypy/lib/distributed/protocol.py ============================================================================== --- pypy/dist/pypy/lib/distributed/protocol.py (original) +++ pypy/dist/pypy/lib/distributed/protocol.py Tue Dec 12 00:04:41 2006 @@ -58,15 +58,21 @@ import types from marshal import dumps +import exceptions class AbstractProtocol(object): immutable_primitives = (str, int, float, long, unicode, bool, types.NotImplementedType) - mutable_primitives = (list, dict, types.FunctionType, types.FrameType) + mutable_primitives = (list, dict, types.FunctionType, types.FrameType, types.TracebackType, + types.CodeType) + exc_dir = dict((val, name) for name, val in exceptions.__dict__.iteritems()) letter_types = { 'l' : list, 'd' : dict, + 'c' : types.CodeType, 't' : tuple, + 'e' : Exception, + 'ex': exceptions, # for instances 'i' : int, 'b' : bool, 'f' : float, @@ -82,6 +88,7 @@ 'type' : type, 'tp' : None, 'fr' : types.FrameType, + 'tb' : types.TracebackType, } type_letters = dict([(value, key) for key, value in letter_types.items()]) assert len(type_letters) == len(letter_types) @@ -95,6 +102,12 @@ def wrap(self, obj): """ Wrap an object as sth prepared for sending """ + def is_element(x, iterable): + try: + return x in iterable + except (TypeError, ValueError): + return False + tp = type(obj) ctrl = get_transparent_controller(obj) if ctrl: @@ -104,6 +117,11 @@ elif tp in self.immutable_primitives: # simple, immutable object, just copy return (self.type_letters[tp], obj) + elif hasattr(obj, '__class__') and obj.__class__ in self.exc_dir: + return (self.type_letters[Exception], (self.exc_dir[obj.__class__], \ + self.wrap(obj.args))) + elif is_element(obj, self.exc_dir): # weird hashing problems + return (self.type_letters[exceptions], self.exc_dir[obj]) elif tp is tuple: # we just pack all of the items return ('t', tuple([self.wrap(elem) for elem in obj])) @@ -147,6 +165,12 @@ p = proxy(tp, ro.perform) ro.obj = p return p + elif tp is Exception: + cls_name, w_args = obj_data + return getattr(exceptions, cls_name)(self.unwrap(w_args)) + elif tp is exceptions: + cls_name = obj_data + return getattr(exceptions, cls_name) elif tp is types.MethodType: w_class, w_name, w_func, w_self = obj_data tp = self.unwrap(w_class) @@ -240,10 +264,17 @@ elif command == 'call': id, name, args, kwargs = data args, kwargs = protocol.unpack_args(args, kwargs) - retval = getattr(protocol.keeper.get_object(id), name)(*args, **kwargs) - send(("finished", wrap(retval))) + try: + retval = getattr(protocol.keeper.get_object(id), name)(*args, **kwargs) + except: + send(("raised", wrap(sys.exc_info()))) + else: + send(("finished", wrap(retval))) elif command == 'finished': return unwrap(data) + elif command == 'raised': + exc, val, tb = unwrap(data) + raise exc, val, tb elif command == 'type_reg': type_id, name, _dict = data protocol.keeper.fake_remote_type(protocol, type_id, name, _dict) @@ -272,7 +303,11 @@ def perform(self, id, name, *args, **kwargs): args, kwargs = self.pack_args(args, kwargs) self.send(('call', (id, name, args, kwargs))) - retval = remote_loop(self) + try: + retval = remote_loop(self) + except: + e, val, tb = sys.exc_info() + raise e, val, tb.tb_next.tb_next return retval def get_remote(self, name): Modified: pypy/dist/pypy/lib/test2/test_distributed.py ============================================================================== --- pypy/dist/pypy/lib/test2/test_distributed.py (original) +++ pypy/dist/pypy/lib/test2/test_distributed.py Tue Dec 12 00:04:41 2006 @@ -180,3 +180,20 @@ xf = protocol.get_remote('f') assert f.f_globals.keys() == xf.f_globals.keys() assert f.f_locals.keys() == xf.f_locals.keys() + + def test_remote_exception(self): + from distributed import test_env + + def raising(): + 1/0 + + protocol = test_env({'raising':raising}) + xr = protocol.get_remote('raising') + try: + xr() + except ZeroDivisionError: + import sys + exc_info, val, tb = sys.exc_info() + #assert tb.tb_next is None + else: + raise AssertionError("Did not raise") From arigo at codespeak.net Tue Dec 12 02:59:04 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 12 Dec 2006 02:59:04 +0100 (CET) Subject: [pypy-svn] r35610 - in pypy/dist/pypy: interpreter module/_stackless Message-ID: <20061212015904.B795410064@code0.codespeak.net> Author: arigo Date: Tue Dec 12 02:59:00 2006 New Revision: 35610 Modified: pypy/dist/pypy/interpreter/pyopcode.py pypy/dist/pypy/module/_stackless/coroutine.py Log: Stackless build works again - a missing 'code' argument in the resume point, and a few typos in the resume logic. Modified: pypy/dist/pypy/interpreter/pyopcode.py ============================================================================== --- pypy/dist/pypy/interpreter/pyopcode.py (original) +++ pypy/dist/pypy/interpreter/pyopcode.py Tue Dec 12 02:59:00 2006 @@ -53,7 +53,8 @@ while True: try: w_result = self.dispatch_bytecode(co_code, next_instr, ec) - rstack.resume_point("dispatch", self, ec, returns=w_result) + rstack.resume_point("dispatch", self, co_code, ec, + returns=w_result) return w_result except OperationError, operr: next_instr = self.handle_operation_error(ec, operr) Modified: pypy/dist/pypy/module/_stackless/coroutine.py ============================================================================== --- pypy/dist/pypy/module/_stackless/coroutine.py (original) +++ pypy/dist/pypy/module/_stackless/coroutine.py Tue Dec 12 02:59:00 2006 @@ -202,36 +202,39 @@ costate = self.costate # now the big fun of recreating tiny things... bottom = resume_state_create(None, "yield_current_frame_to_caller_1") - # resume_point("coroutine__bind", state) + # ("coroutine__bind", state) _bind_frame = resume_state_create(bottom, "coroutine__bind", costate) - # rstack.resume_point("appthunk", costate, returns=w_result) + # ("appthunk", costate, returns=w_result) appthunk_frame = resume_state_create(_bind_frame, "appthunk", costate) chain = appthunk_frame for frame in self.subctx.framestack.items: assert isinstance(frame, PyFrame) - evalframe_frame = resume_state_create(chain, "execute_frame", frame, ec) - eval_frame = resume_state_create(evalframe_frame, "dispatch", frame, ec) - # rstack.resume_point("dispatch_call", self, code, ec) - code = frame.getcode().co_code + # ("execute_frame", self, executioncontext, returns=w_exitvalue) + chain = resume_state_create(chain, "execute_frame", frame, ec) + code = frame.pycode.co_code + # ("dispatch", self, co_code, ec, returns=w_result) + chain = resume_state_create(chain, "dispatch", frame, code, ec) instr = frame.last_instr opcode = ord(code[instr]) assert opcode == pythonopcode.opmap['CALL_FUNCTION'] + # ("dispatch_call", self, co_code, next_instr, ec) + chain = resume_state_create(chain, "dispatch_call", frame, code, + instr+3, ec) instr += 1 - dispatch_call_frame = resume_state_create(eval_frame, "dispatch_call", frame, ec, code, instr+3) oparg = ord(code[instr]) | ord(code[instr + 1]) << 8 if (oparg >> 8) & 0xff == 0: # Only positional arguments nargs = oparg & 0xff - # case1: rstack.resume_point("CALL_FUNCTION", f, nargs, returns=w_result) - call_frame = resume_state_create(dispatch_call_frame, 'CALL_FUNCTION', frame, nargs) + # case1: ("CALL_FUNCTION", f, nargs, returns=w_result) + chain = resume_state_create(chain, 'CALL_FUNCTION', frame, + nargs) else: - # case2: rstack.resume_point("call_function", f, returns=w_result) - call_frame = resume_state_create(dispatch_call_frame, 'call_function', frame) - chain = call_frame + # case2: ("call_function", f, returns=w_result) + chain = resume_state_create(chain, 'call_function', frame) - # rstack.resume_point("w_switch", state, space) + # ("w_switch", state, space) w_switch_frame = resume_state_create(chain, 'w_switch', costate, space) - # resume_point("coroutine_switch", state, returns=incoming_frame) + # ("coroutine_switch", state, returns=incoming_frame) switch_frame = resume_state_create(w_switch_frame, "coroutine_switch", costate) self.frame = switch_frame From arigo at codespeak.net Tue Dec 12 03:06:09 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 12 Dec 2006 03:06:09 +0100 (CET) Subject: [pypy-svn] r35611 - in pypy/dist/pypy: config jit/goal Message-ID: <20061212020609.EC7A910063@code0.codespeak.net> Author: arigo Date: Tue Dec 12 03:06:07 2006 New Revision: 35611 Modified: pypy/dist/pypy/config/translationoption.py pypy/dist/pypy/jit/goal/targetjit.py Log: Port targetjit to the latest config refactoring. Modified: pypy/dist/pypy/config/translationoption.py ============================================================================== --- pypy/dist/pypy/config/translationoption.py (original) +++ pypy/dist/pypy/config/translationoption.py Tue Dec 12 03:06:07 2006 @@ -77,7 +77,8 @@ cmdline=None), ChoiceOption("fork_before", "(UNIX) Create restartable checkpoint before step", - ["annotate", "rtype", "backendopt", "database", "source"], + ["annotate", "rtype", "backendopt", "database", "source", + "hintannotate", "timeshift"], default=None, cmdline="--fork-before"), OptionDescription("backendopt", "Backend Optimization Options", [ Modified: pypy/dist/pypy/jit/goal/targetjit.py ============================================================================== --- pypy/dist/pypy/jit/goal/targetjit.py (original) +++ pypy/dist/pypy/jit/goal/targetjit.py Tue Dec 12 03:06:07 2006 @@ -29,12 +29,12 @@ usage = "target PyPy with JIT" - #def target(self, driver, args): - # from pypy.jit.goal.x import main - # return main, None + def target(self, driver, args): + config = driver.config + config.objspace.usemodules.pypyjit = True + return super(PyPyJITTarget, self).target(driver, args) def handle_config(self, config): - config.objspace.usemodules.pypyjit = True config.translation.backendopt.inline_threshold = 0 config.translation.backendopt.merge_if_blocks = False config.translation.fork_before = 'hintannotate' From mwh at codespeak.net Tue Dec 12 10:31:58 2006 From: mwh at codespeak.net (mwh at codespeak.net) Date: Tue, 12 Dec 2006 10:31:58 +0100 (CET) Subject: [pypy-svn] r35613 - pypy/dist/pypy/translator/llvm Message-ID: <20061212093158.B028C1006E@code0.codespeak.net> Author: mwh Date: Tue Dec 12 10:31:56 2006 New Revision: 35613 Modified: pypy/dist/pypy/translator/llvm/opwriter.py Log: define hint for the llvm generator. now pypy-llvm gets to the point of failing to link (something to do with execv and execve). Modified: pypy/dist/pypy/translator/llvm/opwriter.py ============================================================================== --- pypy/dist/pypy/translator/llvm/opwriter.py (original) +++ pypy/dist/pypy/translator/llvm/opwriter.py Tue Dec 12 10:31:56 2006 @@ -245,7 +245,7 @@ def cast_primitive(self, opr): " works for all casts " - assert len(opr.argrefs) == 1 + #assert len(opr.argrefs) == 1 self.codewriter.cast(opr.retref, opr.argtypes[0], opr.argrefs[0], opr.rettype) same_as = cast_primitive @@ -512,3 +512,6 @@ def debug_print(self, opr): pass # XXX + + def hint(self, opr): + self.same_as(opr) From mwh at codespeak.net Tue Dec 12 11:07:47 2006 From: mwh at codespeak.net (mwh at codespeak.net) Date: Tue, 12 Dec 2006 11:07:47 +0100 (CET) Subject: [pypy-svn] r35618 - pypy/dist/pypy/translator/llvm Message-ID: <20061212100747.0FD2110076@code0.codespeak.net> Author: mwh Date: Tue Dec 12 11:07:44 2006 New Revision: 35618 Modified: pypy/dist/pypy/translator/llvm/genllvm.py Log: slightly XXXish way to get the llvm tests using boehm (and hence pass) again. Modified: pypy/dist/pypy/translator/llvm/genllvm.py ============================================================================== --- pypy/dist/pypy/translator/llvm/genllvm.py (original) +++ pypy/dist/pypy/translator/llvm/genllvm.py Tue Dec 12 11:07:44 2006 @@ -40,8 +40,7 @@ self.translator = translator if config is None: - from pypy.config.pypyoption import get_pypy_config - config = get_pypy_config(translating=True) + config = translator.config self.config = config self.stackless = stackless @@ -328,7 +327,10 @@ # annotate/rtype from pypy.translator.translator import TranslationContext from pypy.translator.backendopt.all import backend_optimizations - translator = TranslationContext() + from pypy.config.pypyoption import get_pypy_config + config = get_pypy_config(translating=True) + config.translation.gc = 'boehm' + translator = TranslationContext(config=config) translator.buildannotator().build_types(function, annotation) translator.buildrtyper().specialize() From mwh at codespeak.net Tue Dec 12 11:12:40 2006 From: mwh at codespeak.net (mwh at codespeak.net) Date: Tue, 12 Dec 2006 11:12:40 +0100 (CET) Subject: [pypy-svn] r35619 - in pypy/dist/pypy/translator: . llvm Message-ID: <20061212101240.32CEE1007D@code0.codespeak.net> Author: mwh Date: Tue Dec 12 11:12:37 2006 New Revision: 35619 Modified: pypy/dist/pypy/translator/driver.py pypy/dist/pypy/translator/llvm/genllvm.py Log: in fact, it's less confusing to have GenLLVM.__init__ not take a config parameter at all. Modified: pypy/dist/pypy/translator/driver.py ============================================================================== --- pypy/dist/pypy/translator/driver.py (original) +++ pypy/dist/pypy/translator/driver.py Tue Dec 12 11:12:37 2006 @@ -473,7 +473,7 @@ # XXX Need more options for policies/llvm-backendoptions here? self.llvmgen = genllvm.GenLLVM(translator, self.config.translation.gc, - self.standalone, config=self.config) + self.standalone) llvm_filename = self.llvmgen.gen_llvm_source(self.entry_point) self.log.info("written: %s" % (llvm_filename,)) Modified: pypy/dist/pypy/translator/llvm/genllvm.py ============================================================================== --- pypy/dist/pypy/translator/llvm/genllvm.py (original) +++ pypy/dist/pypy/translator/llvm/genllvm.py Tue Dec 12 11:12:37 2006 @@ -25,7 +25,7 @@ function_count = {} def __init__(self, translator, gcpolicy, standalone, - debug=False, logging=True, stackless=False, config=None): + debug=False, logging=True, stackless=False): # reset counters LLVMNode.nodename_count = {} @@ -39,9 +39,7 @@ self.standalone = standalone self.translator = translator - if config is None: - config = translator.config - self.config = config + self.config = translator.config self.stackless = stackless # the debug flag is for creating comments of every operation From mwh at codespeak.net Tue Dec 12 11:43:47 2006 From: mwh at codespeak.net (mwh at codespeak.net) Date: Tue, 12 Dec 2006 11:43:47 +0100 (CET) Subject: [pypy-svn] r35620 - pypy/dist/pypy/translator/llvm/test Message-ID: <20061212104347.D8A7D1007B@code0.codespeak.net> Author: mwh Date: Tue Dec 12 11:43:43 2006 New Revision: 35620 Modified: pypy/dist/pypy/translator/llvm/test/test_extfunc.py Log: three skipped, failing tests for execv[e] nicked from genc. Modified: pypy/dist/pypy/translator/llvm/test/test_extfunc.py ============================================================================== --- pypy/dist/pypy/translator/llvm/test/test_extfunc.py (original) +++ pypy/dist/pypy/translator/llvm/test/test_extfunc.py Tue Dec 12 11:43:43 2006 @@ -592,3 +592,56 @@ assert os.WIFEXITED(status1) assert os.WEXITSTATUS(status1) == 4 +if hasattr(posix, 'execv'): + def test_execv(): + py.test.skip("fails to link") + filename = str(udir.join('test_execv.txt')) + executable = sys.executable + def does_stuff(): + progname = str(executable) + l = ['', ''] + l[0] = progname + l[1] = "-c" + l.append('open("%s","w").write("1")' % filename) + pid = os.fork() + if pid == 0: + os.execv(progname, l) + else: + os.waitpid(pid, 0) + return 1 + func = compile_function(does_stuff, []) + func() + assert open(filename).read() == "1" + + def test_execv_raising(): + py.test.skip("fails to link") + def does_stuff(): + l = [] + l.append("asddsadw32eewdfwqdqwdqwd") + os.execv(l[0], l) + return 1 + func = compile_function(does_stuff, []) + py.test.raises(OSError, "func()") + + def test_execve(): + py.test.skip("fails to link") + filename = str(udir.join('test_execve.txt')) + executable = sys.executable + def does_stuff(): + progname = executable + l = [] + l.append(progname) + l.append("-c") + l.append('import os; open("%s", "w").write(os.environ["STH"])' % filename) + env = {} + env["STH"] = "42" + env["sthelse"] = "a" + pid = os.fork() + if pid == 0: + os.execve(progname, l, env) + else: + os.waitpid(pid, 0) + return 1 + func = compile_function(does_stuff, []) + func() + assert open(filename).read() == "42" From pedronis at codespeak.net Tue Dec 12 11:58:01 2006 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Tue, 12 Dec 2006 11:58:01 +0100 (CET) Subject: [pypy-svn] r35621 - pypy/dist/pypy/rpython/lltypesystem Message-ID: <20061212105801.B625F10076@code0.codespeak.net> Author: pedronis Date: Tue Dec 12 11:57:56 2006 New Revision: 35621 Modified: pypy/dist/pypy/rpython/lltypesystem/llmemory.py Log: stop gap solution to the massive __builtin__ test failures. Sometimes even on top of cpython objects go away before their lifeline __del__ is invoked. Modified: pypy/dist/pypy/rpython/lltypesystem/llmemory.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/llmemory.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/llmemory.py Tue Dec 12 11:57:56 2006 @@ -559,8 +559,9 @@ if self.ref is None: return None ob = self.ref() - if ob is None: - raise DanglingPointerError + # xxx stop-gap + #if ob is None: + # raise DanglingPointerError return ob def __repr__(self): if self.ref is None: From mwh at codespeak.net Tue Dec 12 12:34:53 2006 From: mwh at codespeak.net (mwh at codespeak.net) Date: Tue, 12 Dec 2006 12:34:53 +0100 (CET) Subject: [pypy-svn] r35622 - in pypy/dist/pypy/translator: c c/src llvm/module llvm/test Message-ID: <20061212113453.C14C91007E@code0.codespeak.net> Author: mwh Date: Tue Dec 12 12:34:50 2006 New Revision: 35622 Modified: pypy/dist/pypy/translator/c/extfunc.py pypy/dist/pypy/translator/c/src/ll_os.h pypy/dist/pypy/translator/llvm/module/genexterns.c pypy/dist/pypy/translator/llvm/module/protos.h pypy/dist/pypy/translator/llvm/test/test_extfunc.py Log: add some more support functions so LL_os_execv can work entirely with incomplete pointer types. rewrite LL_os_execv in this style. add support to llvm for these helpers, a little as-per-usual-for-llvm hacking and unskip the two exec tests that now pass (the raising on error one doesn't pass yet, haven't tried to find out why yet). Modified: pypy/dist/pypy/translator/c/extfunc.py ============================================================================== --- pypy/dist/pypy/translator/c/extfunc.py (original) +++ pypy/dist/pypy/translator/c/extfunc.py Tue Dec 12 12:34:50 2006 @@ -143,11 +143,21 @@ def _RPyListOfString_New(length=lltype.Signed): return LIST_OF_STR.ll_newlist(length) + def _RPyListOfString_New(length=lltype.Signed): + return LIST_OF_STR.ll_newlist(length) + def _RPyListOfString_SetItem(l=p, index=lltype.Signed, newstring=lltype.Ptr(STR)): rlist.ll_setitem_nonneg(rlist.dum_nocheck, l, index, newstring) + def _RPyListOfString_GetItem(l=p, + index=lltype.Signed): + return rlist.ll_getitem_fast(l, index) + + def _RPyListOfString_Length(l=p): + return rlist.ll_length(l) + for fname, f in locals().items(): if isinstance(f, types.FunctionType): # XXX this is painful :( Modified: pypy/dist/pypy/translator/c/src/ll_os.h ============================================================================== --- pypy/dist/pypy/translator/c/src/ll_os.h (original) +++ pypy/dist/pypy/translator/c/src/ll_os.h Tue Dec 12 12:34:50 2006 @@ -396,11 +396,11 @@ #if defined(HAVE_EXECV) && defined(HAVE_RPY_LIST_OF_STRING) char** get_slist(RPyListOfString *args) { - int i, nargs = args->l_length; + int i, nargs = _RPyListOfString_Length(args); char **slist = malloc((nargs+1) * sizeof(char*)); if (slist) { for (i=0; il_items->items[i]); + slist[i] = RPyString_AsString(_RPyListOfString_GetItem(args, i)); slist[nargs] = NULL; return slist; } else { Modified: pypy/dist/pypy/translator/llvm/module/genexterns.c ============================================================================== --- pypy/dist/pypy/translator/llvm/module/genexterns.c (original) +++ pypy/dist/pypy/translator/llvm/module/genexterns.c Tue Dec 12 12:34:50 2006 @@ -1,5 +1,9 @@ // append some genc files here manually from python +//#include "c/src/support.h" +#ifdef _RPyListOfString_New /* :-( */ +# define HAVE_RPY_LIST_OF_STRING +#endif #include "c/src/thread.h" #include "c/src/ll_os.h" #include "c/src/ll_math.h" Modified: pypy/dist/pypy/translator/llvm/module/protos.h ============================================================================== --- pypy/dist/pypy/translator/llvm/module/protos.h (original) +++ pypy/dist/pypy/translator/llvm/module/protos.h Tue Dec 12 12:34:50 2006 @@ -19,6 +19,8 @@ #ifdef RPyListOfString RPyListOfString *_RPyListOfString_New(long); void _RPyListOfString_SetItem(RPyListOfString *, int, RPyString *); + RPyString *_RPyListOfString_GetItem(RPyListOfString *, int); + int _RPyListOfString_Length(RPyListOfString *); #endif // XXX end of proto hacks Modified: pypy/dist/pypy/translator/llvm/test/test_extfunc.py ============================================================================== --- pypy/dist/pypy/translator/llvm/test/test_extfunc.py (original) +++ pypy/dist/pypy/translator/llvm/test/test_extfunc.py Tue Dec 12 12:34:50 2006 @@ -594,7 +594,6 @@ if hasattr(posix, 'execv'): def test_execv(): - py.test.skip("fails to link") filename = str(udir.join('test_execv.txt')) executable = sys.executable def does_stuff(): @@ -614,7 +613,7 @@ assert open(filename).read() == "1" def test_execv_raising(): - py.test.skip("fails to link") + py.test.skip("does not raise") def does_stuff(): l = [] l.append("asddsadw32eewdfwqdqwdqwd") @@ -624,7 +623,6 @@ py.test.raises(OSError, "func()") def test_execve(): - py.test.skip("fails to link") filename = str(udir.join('test_execve.txt')) executable = sys.executable def does_stuff(): From mwh at codespeak.net Tue Dec 12 12:37:49 2006 From: mwh at codespeak.net (mwh at codespeak.net) Date: Tue, 12 Dec 2006 12:37:49 +0100 (CET) Subject: [pypy-svn] r35623 - pypy/dist/pypy/translator/llvm/test Message-ID: <20061212113749.CE3501007E@code0.codespeak.net> Author: mwh Date: Tue Dec 12 12:37:47 2006 New Revision: 35623 Modified: pypy/dist/pypy/translator/llvm/test/test_extfunc.py Log: so that was just a problem in the test. llvm now supports os.execv and os.execve. Modified: pypy/dist/pypy/translator/llvm/test/test_extfunc.py ============================================================================== --- pypy/dist/pypy/translator/llvm/test/test_extfunc.py (original) +++ pypy/dist/pypy/translator/llvm/test/test_extfunc.py Tue Dec 12 12:37:47 2006 @@ -613,14 +613,18 @@ assert open(filename).read() == "1" def test_execv_raising(): - py.test.skip("does not raise") def does_stuff(): l = [] l.append("asddsadw32eewdfwqdqwdqwd") - os.execv(l[0], l) - return 1 + try: + os.execv(l[0], l) + except OSError: + return 1 + else: + return 0 func = compile_function(does_stuff, []) - py.test.raises(OSError, "func()") + res = func() + assert res == 1 def test_execve(): filename = str(udir.join('test_execve.txt')) From arigo at codespeak.net Tue Dec 12 12:40:22 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 12 Dec 2006 12:40:22 +0100 (CET) Subject: [pypy-svn] r35624 - pypy/dist/pypy/rpython Message-ID: <20061212114022.66BE410086@code0.codespeak.net> Author: arigo Date: Tue Dec 12 12:40:21 2006 New Revision: 35624 Modified: pypy/dist/pypy/rpython/annlowlevel.py Log: A hackish fix for the case where building the cached object fails... or raises py.test.Skip, as in some of the test_genc_ts tests in the i386 backend :-/ Modified: pypy/dist/pypy/rpython/annlowlevel.py ============================================================================== --- pypy/dist/pypy/rpython/annlowlevel.py (original) +++ pypy/dist/pypy/rpython/annlowlevel.py Tue Dec 12 12:40:21 2006 @@ -492,5 +492,13 @@ return d[args] except KeyError: instance = d[args] = selfcls.__new__(selfcls, *args) - instance.__init__(*args) + try: + instance.__init__(*args) + except: + # If __init__ fails, remove the 'instance' from d. + # That's a "best effort" attempt, it's not really enough + # in theory because some other place might have grabbed + # a reference to the same broken 'instance' in the meantime + del d[args] + raise return instance From fijal at codespeak.net Tue Dec 12 13:05:22 2006 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 12 Dec 2006 13:05:22 +0100 (CET) Subject: [pypy-svn] r35626 - in pypy/dist/pypy/tool: pytest test Message-ID: <20061212120522.98A871007D@code0.codespeak.net> Author: fijal Date: Tue Dec 12 13:05:17 2006 New Revision: 35626 Modified: pypy/dist/pypy/tool/pytest/appsupport.py pypy/dist/pypy/tool/test/test_pytestsupport.py Log: Fixed tests. Modified: pypy/dist/pypy/tool/pytest/appsupport.py ============================================================================== --- pypy/dist/pypy/tool/pytest/appsupport.py (original) +++ pypy/dist/pypy/tool/pytest/appsupport.py Tue Dec 12 13:05:17 2006 @@ -17,9 +17,13 @@ #except OperationError: # self.path = space.unwrap(space.getattr( self.path = py.path.local(space.str_w(self.w_file)) + self.space = space def fullsource(self): - return py.code.Source(self.path.read(mode="rU")) + try: + return self.space.str_w(self.w_file).__source__ + except AttributeError: + return py.code.Source(self.path.read(mode="rU")) fullsource = property(fullsource, None, None, "Full source of AppCode") class AppFrame(py.code.Frame): Modified: pypy/dist/pypy/tool/test/test_pytestsupport.py ============================================================================== --- pypy/dist/pypy/tool/test/test_pytestsupport.py (original) +++ pypy/dist/pypy/tool/test/test_pytestsupport.py Tue Dec 12 13:05:17 2006 @@ -15,7 +15,7 @@ import sys co = PyCode._from_code(space, somefunc.func_code) pyframe = PyFrame(space, co, space.newdict(), None) - runner = AppFrame(pyframe) + runner = AppFrame(space, pyframe) exprinfo.run("f = lambda x: x+1", runner) msg = exprinfo.interpret("assert isinstance(f(2), float)", runner) assert msg.startswith("assert isinstance(3, float)\n" From niko at codespeak.net Tue Dec 12 15:14:05 2006 From: niko at codespeak.net (niko at codespeak.net) Date: Tue, 12 Dec 2006 15:14:05 +0100 (CET) Subject: [pypy-svn] r35631 - pypy/extradoc/sprintinfo/leysin-winter-2007 Message-ID: <20061212141405.564E010084@code0.codespeak.net> Author: niko Date: Tue Dec 12 15:14:03 2006 New Revision: 35631 Modified: pypy/extradoc/sprintinfo/leysin-winter-2007/people.txt Log: add my dates Modified: pypy/extradoc/sprintinfo/leysin-winter-2007/people.txt ============================================================================== --- pypy/extradoc/sprintinfo/leysin-winter-2007/people.txt (original) +++ pypy/extradoc/sprintinfo/leysin-winter-2007/people.txt Tue Dec 12 15:14:03 2006 @@ -17,6 +17,7 @@ Anders Chrigstroem 6th-15th Ermina Samuele Pedroni 6th-15th Ermina Michael Hudson 7th-15th Ermina +Niko Matsakis 9th-14th Ermina ==================== ============== ===================== People on the following list were present at previous sprints: From pedronis at codespeak.net Tue Dec 12 15:16:55 2006 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Tue, 12 Dec 2006 15:16:55 +0100 (CET) Subject: [pypy-svn] r35632 - pypy/dist/pypy/doc Message-ID: <20061212141655.AA2241007E@code0.codespeak.net> Author: pedronis Date: Tue Dec 12 15:16:52 2006 New Revision: 35632 Modified: pypy/dist/pypy/doc/draft-jit-outline.txt Log: first try at an intro Modified: pypy/dist/pypy/doc/draft-jit-outline.txt ============================================================================== --- pypy/dist/pypy/doc/draft-jit-outline.txt (original) +++ pypy/dist/pypy/doc/draft-jit-outline.txt Tue Dec 12 15:16:52 2006 @@ -5,7 +5,69 @@ Introduction ============= -Intepreters to compilers, psyco parallel... +.. Interpreters to compilers, psyco parallel... + +One the of the central goals of the PyPy project is to automatically +produce a Just in Time Compiler from the interpreter, with as little +as possible intervention on the interpreter codebase itself. The Just +in Time Compiler should be another aspect as much as possible +transparently introduced by and during the translation process. + +Partial evaluation techniques should, at least theoretically, allow +such a derivation of a compiler from an interpreter. XXX scalability +issues references ... + +The forest of flow graphs that the translation process generates and +transforms constitutes a reasonable base for the necessary analyses. +That's a further reason why having an high-level runnable and +analysable description of the language was always a central tenet of +the project. + +Transforming an interpreter into a compiler involves constructing a so +called generating extension, which takes input programs to the +interpreter, and produces what would be the output of partial +evaluating the interpreter with the input data left variable and the +input program being fixed. The generating extension is essentially +capable of compiling the input programs. + +Generating extensions can be produced by self-applying partial evaluators, +but this approach may lead to not optimal results or be not scalable + +For PyPy, our approach aims at producing the generating extension more +directly from the analysed interpreter in the form of a forest of flow +graphs. We call such process *timeshifting*. + +To be able to achieve this, gathering binding time information is +crucial, this means for an input program distinguishing values in the +data-flow that are compile-time bound and immutable at run-time, +versus respectively runtime values. + +Currently we base the binding time computation on propagating the +information based on a few hint inserted in the interpreter. Propagation +is implemented by reusing our annotation/type inference framework XXX +ref. + +The code produced by a generating extension for an input program may +not be good, especially for a dynamic language, because essentially +the input program doesn't contain enough information to generate good +code. What is really desired is not a generating extension doing +static compilation, but one capable of dynamic compilation, exploiting +runtime information in its result, or using a different terminology +capable of producing code that is specialised with respect to some of +the run-time information, for example language-level types. + +Inspired by Psyco, which in some sense is such a specialising +generating extension for Python, but hand-written, we added support +for so-called *promotion* to our framework for producing generating +extensions. + +Simply put, promotion on a value stops compilation when encountered, +when the same point is reached at run-time compilation is restarted +and the current run-time value is used and propagated as a compile-time +value. Concretely the promotion expands into a switch to choose based +on the run-time value one of the possible specialised code paths, plus +a default case to compile further specialised paths. This can be also +thought as a generalisation of polymorphic inline caches XXX ref. Hint-Annotation and Compile Time Values From pedronis at codespeak.net Tue Dec 12 15:57:59 2006 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Tue, 12 Dec 2006 15:57:59 +0100 (CET) Subject: [pypy-svn] r35633 - pypy/dist/pypy/jit Message-ID: <20061212145759.D3C231007D@code0.codespeak.net> Author: pedronis Date: Tue Dec 12 15:57:57 2006 New Revision: 35633 Modified: pypy/dist/pypy/jit/TODO.txt Log: merge done! Modified: pypy/dist/pypy/jit/TODO.txt ============================================================================== --- pypy/dist/pypy/jit/TODO.txt (original) +++ pypy/dist/pypy/jit/TODO.txt Tue Dec 12 15:57:57 2006 @@ -5,9 +5,6 @@ with implicit exceptions only if they are inside a precise try:except: -- stability + do something about bytecode_trace such that the jit - branch can be merged - - global merge point and portal should delegate their cache impl. to the application (to allow keeping things alive correctly) From afayolle at codespeak.net Tue Dec 12 16:03:14 2006 From: afayolle at codespeak.net (afayolle at codespeak.net) Date: Tue, 12 Dec 2006 16:03:14 +0100 (CET) Subject: [pypy-svn] r35634 - pypy/dist/pypy/tool/build Message-ID: <20061212150314.14A9D10083@code0.codespeak.net> Author: afayolle Date: Tue Dec 12 16:03:13 2006 New Revision: 35634 Modified: pypy/dist/pypy/tool/build/client.py Log: added isatty method on OutputBuffer (to satisfy ansi_print) Modified: pypy/dist/pypy/tool/build/client.py ============================================================================== --- pypy/dist/pypy/tool/build/client.py (original) +++ pypy/dist/pypy/tool/build/client.py Tue Dec 12 16:03:13 2006 @@ -140,3 +140,5 @@ def getvalue(self): return self.buffer.getvalue() + def isatty(self): + return False From mwh at codespeak.net Tue Dec 12 16:47:33 2006 From: mwh at codespeak.net (mwh at codespeak.net) Date: Tue, 12 Dec 2006 16:47:33 +0100 (CET) Subject: [pypy-svn] r35635 - in pypy/dist/pypy/translator/llvm: . test Message-ID: <20061212154733.378031007E@code0.codespeak.net> Author: mwh Date: Tue Dec 12 16:47:31 2006 New Revision: 35635 Modified: pypy/dist/pypy/translator/llvm/funcnode.py pypy/dist/pypy/translator/llvm/test/test_genllvm.py Log: support for switches without defaults in genllvm. Modified: pypy/dist/pypy/translator/llvm/funcnode.py ============================================================================== --- pypy/dist/pypy/translator/llvm/funcnode.py (original) +++ pypy/dist/pypy/translator/llvm/funcnode.py Tue Dec 12 16:47:31 2006 @@ -33,13 +33,14 @@ class FuncNode(ConstantLLVMNode): - __slots__ = "db value ref graph block_to_name".split() + __slots__ = "db value ref graph block_to_name bad_switch_block".split() def __init__(self, db, value): self.db = db self.value = value self.ref = self.make_ref('%pypy_', value.graph.name) self.graph = value.graph + self.bad_switch_block = False #XXX experimental #from pypy.translator.llvm.backendopt.mergemallocs import merge_mallocs @@ -90,6 +91,14 @@ break else: self.write_block(codewriter, block) + if self.bad_switch_block: + codewriter.label('badswitch') + codewriter._indent('call void %abort()') + rettype = self.graph.getreturnvar().concretetype + if rettype is lltype.Void: + codewriter._indent('ret') + else: + codewriter._indent('ret %s 0'%(self.db.repr_type(rettype))) codewriter.closefunc() def writeglobalconstants(self, codewriter): @@ -177,8 +186,13 @@ value_labels.append( (exitcase, self.block_to_name[link.target]) ) - codewriter.switch(condtype, cond, - self.block_to_name[defaultlink.target], value_labels) + if defaultlink: + defaultblockname = self.block_to_name[defaultlink.target] + else: + defaultblockname = 'badswitch' + self.bad_switch_block = True + + codewriter.switch(condtype, cond, defaultblockname, value_labels) else: raise BranchException("exitswitch type '%s' not supported" % Modified: pypy/dist/pypy/translator/llvm/test/test_genllvm.py ============================================================================== --- pypy/dist/pypy/translator/llvm/test/test_genllvm.py (original) +++ pypy/dist/pypy/translator/llvm/test/test_genllvm.py Tue Dec 12 16:47:31 2006 @@ -441,3 +441,21 @@ assert f(0) == 0 +def test_switch_no_default(): + from pypy.objspace.flow.model import FunctionGraph, Block, Constant, Link + from pypy.rpython.lltypesystem.lltype import FuncType, Signed, functionptr + from pypy.translator.unsimplify import varoftype + block = Block([varoftype(Signed)]) + block.exitswitch = block.inputargs[0] + graph = FunctionGraph("t", block, varoftype(Signed)) + links = [] + for i in range(10): + links.append(Link([Constant(i*i, Signed)], graph.returnblock, i)) + links[-1].llexitcase = i + block.closeblock(*links) + fptr = functionptr(FuncType([Signed], Signed), "t", graph=graph) + def func(x): + return fptr(x) + f = compile_function(func, [int]) + res = f(4) + assert res == 16 From mwh at codespeak.net Tue Dec 12 21:23:06 2006 From: mwh at codespeak.net (mwh at codespeak.net) Date: Tue, 12 Dec 2006 21:23:06 +0100 (CET) Subject: [pypy-svn] r35655 - pypy/dist/pypy/translator/llvm Message-ID: <20061212202306.7B2C610083@code0.codespeak.net> Author: mwh Date: Tue Dec 12 21:23:05 2006 New Revision: 35655 Modified: pypy/dist/pypy/translator/llvm/funcnode.py Log: support a lot more return types for functions with multiple switches Modified: pypy/dist/pypy/translator/llvm/funcnode.py ============================================================================== --- pypy/dist/pypy/translator/llvm/funcnode.py (original) +++ pypy/dist/pypy/translator/llvm/funcnode.py Tue Dec 12 21:23:05 2006 @@ -96,7 +96,13 @@ codewriter._indent('call void %abort()') rettype = self.graph.getreturnvar().concretetype if rettype is lltype.Void: - codewriter._indent('ret') + codewriter._indent('ret void') + elif rettype is lltype.Bool: + codewriter._indent('ret bool false') + elif rettype is lltype.Float: + codewriter._indent('ret double 0.0') + elif isinstance(rettype, lltype.Ptr): + codewriter._indent('ret %s null'%(self.db.repr_type(rettype))) else: codewriter._indent('ret %s 0'%(self.db.repr_type(rettype))) codewriter.closefunc() From pedronis at codespeak.net Wed Dec 13 12:46:18 2006 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Wed, 13 Dec 2006 12:46:18 +0100 (CET) Subject: [pypy-svn] r35666 - pypy/dist/pypy/translator/llvm/test Message-ID: <20061213114618.AFEC110071@code0.codespeak.net> Author: pedronis Date: Wed Dec 13 12:46:15 2006 New Revision: 35666 Modified: pypy/dist/pypy/translator/llvm/test/test_symbolic.py Log: skip if needed Modified: pypy/dist/pypy/translator/llvm/test/test_symbolic.py ============================================================================== --- pypy/dist/pypy/translator/llvm/test/test_symbolic.py (original) +++ pypy/dist/pypy/translator/llvm/test/test_symbolic.py Wed Dec 13 12:46:15 2006 @@ -94,6 +94,7 @@ assert res == 51 def test_computed_int_symbolic(): + llvm_test() too_early = True def compute_fn(): assert not too_early From arigo at codespeak.net Wed Dec 13 13:10:35 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 13 Dec 2006 13:10:35 +0100 (CET) Subject: [pypy-svn] r35667 - pypy/dist/pypy/doc Message-ID: <20061213121035.ACE8610077@code0.codespeak.net> Author: arigo Date: Wed Dec 13 13:10:33 2006 New Revision: 35667 Modified: pypy/dist/pypy/doc/news.txt Log: Link to the Leysin sprint. Modified: pypy/dist/pypy/doc/news.txt ============================================================================== --- pypy/dist/pypy/doc/news.txt (original) +++ pypy/dist/pypy/doc/news.txt Wed Dec 13 13:10:33 2006 @@ -16,6 +16,29 @@ .. _eventhistory: eventhistory.html +Leysin Winter Sports Sprint, 8th - 14th January 2007 +================================================================== + +.. raw:: html + +
+ +The next PyPy sprint will be in Leysin, Switzerland, for the fourth +time. This sprint is a fully public sprint and will also be a kick-off +for the final work on the upcoming PyPy 1.0 release (scheduled for +mid-February). See the `Leysin announcement`_ for details. + +The sprint is the last best chance for students looking for a `"summer" job +with PyPy`_ this winter! + +.. raw:: html + +
+ +.. _`Leysin announcement`: http://codespeak.net/pypy/extradoc/sprintinfo/leysin-winter-2007/announcement.html +.. _`"summer" job with PyPy`: http://codespeak.net/pypy/dist/pypy/doc/summer-of-pypy.html + + Duesseldorf sprint #2, 30th October - 5th November over ================================================================== From pedronis at codespeak.net Wed Dec 13 13:12:48 2006 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Wed, 13 Dec 2006 13:12:48 +0100 (CET) Subject: [pypy-svn] r35668 - pypy/dist/pypy/translator/js/test Message-ID: <20061213121248.A43B210078@code0.codespeak.net> Author: pedronis Date: Wed Dec 13 13:12:45 2006 New Revision: 35668 Modified: pypy/dist/pypy/translator/js/test/runtest.py Log: XXX about why the failures in test_rpython Modified: pypy/dist/pypy/translator/js/test/runtest.py ============================================================================== --- pypy/dist/pypy/translator/js/test/runtest.py (original) +++ pypy/dist/pypy/translator/js/test/runtest.py Wed Dec 13 13:12:45 2006 @@ -141,6 +141,13 @@ # self._ann = ann # self._cli_func = compile_function(fn, ann) # return self._cli_func + + # XXX this will capture and use constant values + # for some test, for example reused from rpython/test + # it may result in annotation failures + # because some paths are not considered! + # that's what is provoking the failures + # in test_rpython def f(): res = fn(*args) if isinstance(res, type(None)): From antocuni at codespeak.net Wed Dec 13 13:13:10 2006 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Wed, 13 Dec 2006 13:13:10 +0100 (CET) Subject: [pypy-svn] r35669 - pypy/extradoc/sprintinfo/leysin-winter-2007 Message-ID: <20061213121310.485991007C@code0.codespeak.net> Author: antocuni Date: Wed Dec 13 13:13:09 2006 New Revision: 35669 Modified: pypy/extradoc/sprintinfo/leysin-winter-2007/people.txt Log: My dates Modified: pypy/extradoc/sprintinfo/leysin-winter-2007/people.txt ============================================================================== --- pypy/extradoc/sprintinfo/leysin-winter-2007/people.txt (original) +++ pypy/extradoc/sprintinfo/leysin-winter-2007/people.txt Wed Dec 13 13:13:09 2006 @@ -18,6 +18,7 @@ Samuele Pedroni 6th-15th Ermina Michael Hudson 7th-15th Ermina Niko Matsakis 9th-14th Ermina +Antonio Cuni 7th-15th Ermina ==================== ============== ===================== People on the following list were present at previous sprints: @@ -45,7 +46,6 @@ Carl Friedrich Bolz ? ? Richard Emslie ? ? Johan Hahn ? ? -Antonio Cuni ? ? Maciej Fijalkowski ? ? Stephan Diehl ? ? Niko Matsakis ? ? From arigo at codespeak.net Wed Dec 13 14:02:10 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 13 Dec 2006 14:02:10 +0100 (CET) Subject: [pypy-svn] r35672 - pypy/dist/pypy/doc Message-ID: <20061213130210.9562810078@code0.codespeak.net> Author: arigo Date: Wed Dec 13 14:02:04 2006 New Revision: 35672 Modified: pypy/dist/pypy/doc/draft-jit-outline.txt Log: Test check-in. Modified: pypy/dist/pypy/doc/draft-jit-outline.txt ============================================================================== --- pypy/dist/pypy/doc/draft-jit-outline.txt (original) +++ pypy/dist/pypy/doc/draft-jit-outline.txt Wed Dec 13 14:02:04 2006 @@ -53,6 +53,7 @@ code. What is really desired is not a generating extension doing static compilation, but one capable of dynamic compilation, exploiting runtime information in its result, or using a different terminology +(XXX explain differently the following) capable of producing code that is specialised with respect to some of the run-time information, for example language-level types. @@ -89,6 +90,7 @@ intro and basics + Transform vs hrtyping ----------------------- From arigo at codespeak.net Wed Dec 13 14:54:52 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 13 Dec 2006 14:54:52 +0100 (CET) Subject: [pypy-svn] r35674 - pypy/dist/pypy/doc Message-ID: <20061213135452.3797810078@code0.codespeak.net> Author: arigo Date: Wed Dec 13 14:54:51 2006 New Revision: 35674 Modified: pypy/dist/pypy/doc/draft-jit-outline.txt Log: Dummy checkin Modified: pypy/dist/pypy/doc/draft-jit-outline.txt ============================================================================== --- pypy/dist/pypy/doc/draft-jit-outline.txt (original) +++ pypy/dist/pypy/doc/draft-jit-outline.txt Wed Dec 13 14:54:51 2006 @@ -90,7 +90,6 @@ intro and basics - Transform vs hrtyping ----------------------- From arigo at codespeak.net Wed Dec 13 14:58:22 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 13 Dec 2006 14:58:22 +0100 (CET) Subject: [pypy-svn] r35675 - pypy/dist/pypy/doc Message-ID: <20061213135822.9600B1007B@code0.codespeak.net> Author: arigo Date: Wed Dec 13 14:58:21 2006 New Revision: 35675 Modified: pypy/dist/pypy/doc/draft-jit-outline.txt Log: Another test check-in... Modified: pypy/dist/pypy/doc/draft-jit-outline.txt ============================================================================== --- pypy/dist/pypy/doc/draft-jit-outline.txt (original) +++ pypy/dist/pypy/doc/draft-jit-outline.txt Wed Dec 13 14:58:21 2006 @@ -88,7 +88,7 @@ Timeshifting: transforming interpreter into compilers ====================================================== -intro and basics +intro and basics... Transform vs hrtyping ----------------------- From arigo at codespeak.net Wed Dec 13 15:02:47 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 13 Dec 2006 15:02:47 +0100 (CET) Subject: [pypy-svn] r35676 - pypy/dist/pypy/doc Message-ID: <20061213140247.E4B301007E@code0.codespeak.net> Author: arigo Date: Wed Dec 13 15:02:46 2006 New Revision: 35676 Modified: pypy/dist/pypy/doc/draft-jit-outline.txt Log: More dunny check-ins! Modified: pypy/dist/pypy/doc/draft-jit-outline.txt ============================================================================== --- pypy/dist/pypy/doc/draft-jit-outline.txt (original) +++ pypy/dist/pypy/doc/draft-jit-outline.txt Wed Dec 13 15:02:46 2006 @@ -88,7 +88,7 @@ Timeshifting: transforming interpreter into compilers ====================================================== -intro and basics... +intro and basics Transform vs hrtyping ----------------------- From guido at codespeak.net Wed Dec 13 15:50:00 2006 From: guido at codespeak.net (guido at codespeak.net) Date: Wed, 13 Dec 2006 15:50:00 +0100 (CET) Subject: [pypy-svn] r35679 - in pypy/dist/pypy/tool/build: . bin test Message-ID: <20061213145000.2047510069@code0.codespeak.net> Author: guido Date: Wed Dec 13 15:49:47 2006 New Revision: 35679 Added: pypy/dist/pypy/tool/build/build.py pypy/dist/pypy/tool/build/test/repo.py pypy/dist/pypy/tool/build/test/test_build.py pypy/dist/pypy/tool/build/tooloption.py Removed: pypy/dist/pypy/tool/build/test/test_request_storage.py Modified: pypy/dist/pypy/tool/build/bin/client pypy/dist/pypy/tool/build/bin/startcompile pypy/dist/pypy/tool/build/client.py pypy/dist/pypy/tool/build/config.py pypy/dist/pypy/tool/build/server.py pypy/dist/pypy/tool/build/test/fake.py pypy/dist/pypy/tool/build/test/test_client.py pypy/dist/pypy/tool/build/test/test_pypybuilder.py pypy/dist/pypy/tool/build/test/test_server.py Log: Relatively large refactoring to implement support for choosing a revision (or a range of revisions) to build. The client still doesn't actually update to the revision, so it's not entirely functional yet, but it's all there. I changed the way the data is passed around: instead of passing a tuple with info from the startcompile script to the server, which passes it to the client, a special object (BuildRequest) is passed around. This object contains info about the email address, the revision and revision range, etc. When done compiling, this object is serialized and stored on the BuildPath along with the rest of the data. The RequestStorage is removed, since the caching it did is no longer possible (revision range spoils this). Modified: pypy/dist/pypy/tool/build/bin/client ============================================================================== --- pypy/dist/pypy/tool/build/bin/client (original) +++ pypy/dist/pypy/tool/build/bin/client Wed Dec 13 15:49:47 2006 @@ -3,10 +3,13 @@ import path import sys import random +import traceback from pypy.tool.build import config as buildconfig +from pypy.interpreter.error import OperationError from py.execnet import SshGateway, PopenGateway from pypy.tool.build.client import init, zip_result, OutputBuffer +from pypy.tool.build import build from pypy.config.config import to_optparse, Config from pypy.config import pypyoption @@ -28,18 +31,27 @@ try: try: while 1: - data = channel.receive() - if isinstance(data, str): - continue - if not isinstance(data, tuple): # needs more checks here + # receive compile requests + request = channel.receive() + if isinstance(request, str): + try: + request = build.BuildRequest.fromstring(request) + except (KeyError, SyntaxError), e: + print ('exception occurred when trying to interpret the ' + 'following request:') + print request + print + print 'going to continue' + continue + else: raise ValueError( 'received wrong unexpected data of type %s' % ( - type(data),) + type(request),) ) - sysinfo, compileinfo = data accepting = True for checker in buildconfig.client_checkers: - if not checker(sysinfo, compileinfo): + if not checker(request.sysinfo, request.compileinfo): + print 'request refused by checker', checker.func_name accepting = False break channel.send(accepting) @@ -47,25 +59,43 @@ print 'refusing compilation' continue # XXX we should compile here, using data dict for info - print 'compilation requested for info %r\n\nbuilding...' % ( - data,) + print 'compilation requested for %s\nbuilding...\n' % (request,) config = pypyoption.get_pypy_config() - config.override(compileinfo) + config.override(request.compileinfo) buffer = OutputBuffer(sys.__stderr__) sys.stdout = buffer sys.stderr = buffer + exception_occurred = False try: - driver = TranslationDriver.from_targetspec( - targetpypystandalone.__dict__, config=config, - default_goal='compile') - driver.proceed(['compile']) + try: + driver = TranslationDriver.from_targetspec( + targetpypystandalone.__dict__, config=config, + default_goal='compile') + driver.proceed(['compile']) + except Exception, e: + if isinstance(e, OperationError): + print dir(e) + print repr(e.msg) + exception_occurred = True + exc, e, tb = sys.exc_info() + print '=' * 79 + print 'Exception during compilation:' + print '%s: %s' % (exc, e) + print + print '\n'.join(traceback.format_tb(tb)) + print '=' * 79 + del tb finally: sys.stdout = sys.__stdout__ sys.stderr = sys.__stderr__ - # send over zip data, end with a None - zip_result(udir, channel) + if not exception_occurred: + # send over zip data, end with a None + zip_result(udir, channel) + else: + # just send the None + channel.send(None) # send over logs channel.send(buffer.getvalue()) @@ -76,3 +106,4 @@ finally: channel.close() gw.exit() + Modified: pypy/dist/pypy/tool/build/bin/startcompile ============================================================================== --- pypy/dist/pypy/tool/build/bin/startcompile (original) +++ pypy/dist/pypy/tool/build/bin/startcompile Wed Dec 13 15:49:47 2006 @@ -4,14 +4,17 @@ import sys import random from pypy.tool.build import config +from pypy.tool.build import build +from pypy.tool.build.tooloption import tool_config -def parse_options(config): +def parse_options(config, tool_config): # merge system + compile options into one optionparser from py.compat.optparse import OptionParser, OptionGroup from pypy.config.config import to_optparse optparser = to_optparse(config.system_config) to_optparse(config.compile_config, parser=optparser) + to_optparse(tool_config, parser=optparser) (options, args) = optparser.parse_args() @@ -26,7 +29,8 @@ try: from pypy.tool.build import ppbserver - ret = ppbserver.compile(%r, (%r, %r)) + from pypy.tool.build import build + ret = ppbserver.compile(%r) channel.send(ret) channel.close() except: @@ -37,22 +41,27 @@ channel.send(line[:-1]) del tb """ -def init(gw, sysinfo, compileinfo, path, email, port=12321): +def init(gw, request, path, port=12321): from pypy.tool.build import execnetconference conference = execnetconference.conference(gw, port, False) - channel = conference.remote_exec(initcode % (path, email, sysinfo, - compileinfo)) + channel = conference.remote_exec(initcode % (path, request)) return channel if __name__ == '__main__': from py.execnet import SshGateway, PopenGateway from pypy.config.config import make_dict - optparser, options, args = parse_options(config) + optparser, options, args = parse_options(config, tool_config) sysinfo = make_dict(config.system_config) compileinfo = make_dict(config.compile_config) + + buildrequest = build.BuildRequest(args[0], sysinfo, compileinfo, + config.svnpath_to_url( + tool_config.svnpath), + tool_config.svnrev, + tool_config.revrange) print 'going to start compile job with info:' for k, v in sysinfo.items(): @@ -66,8 +75,8 @@ gw = PopenGateway() else: gw = SshGateway(config.server) - channel = init(gw, sysinfo, compileinfo, config.path, args[0], - port=config.port) + + channel = init(gw, buildrequest, config.path, port=config.port) data = channel.receive() if type(data) == str: print data @@ -85,3 +94,4 @@ print 'you will be mailed once it\'s ready' channel.close() gw.exit() + Added: pypy/dist/pypy/tool/build/build.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/tool/build/build.py Wed Dec 13 15:49:47 2006 @@ -0,0 +1,136 @@ +import py +from py.__.path.local.local import LocalPath + +def normalize_revision(svnurl, rev, highest_if_error=True): + """ return the actual revision of a certain repo state + + if the string HEAD is provided, this looks up the trunk revision, if + the provided revision is an int (or string containing an int), the + revision id of the last revision before rev is returned, including (so + if rev itself had changes, rev is returned) + """ + if rev == 'HEAD': + u = py.path.svnurl(svnurl) + else: + rev = int(rev) + u = py.path.svnurl(svnurl, rev=rev) + try: + return int(u.info().created_rev) + except py.error.Error: + if not highest_if_error: + raise + u = py.path.svnurl(svnurl) + return int(u.info().created_rev) + +class BuildPath(LocalPath): + def _request(self): + req = self.join('request') + if not req.check(): + return None + return BuildRequest.fromstring(req.read()) + + def _set_request(self, request): + self.ensure('request', file=True).write(request.serialize()) + + request = property(_request, _set_request) + + def _zipfile(self): + return self.ensure('data.zip', file=True) + + def _set_zipfile(self, iterable): + # XXX not in use right now... + fp = self._zipfile().open('w') + try: + for chunk in iterable: + fp.write(chunk) + finally: + fp.close() + + zipfile = property(_zipfile, _set_zipfile) + + def _log(self): + log = self.join('log') + if not log.check(): + return '' + return log.read() + + def _set_log(self, data): + self.ensure('log', file=True).write(data) + + log = property(_log, _set_log) + + def _done(self): + return not not self.log + done = property(_done) + +class Build(object): + """ build data """ + def __init__(self, buildrequest, buildpath): + self.request = buildrequest + self.path = buildpath + +class BuildRequest(object): + """ build request data + + holds information about a build request, and some functionality to + serialize and unserialize itself + """ + def __init__(self, email, sysinfo, compileinfo, svnurl, svnrev, revrange): + self.email = email + self.sysinfo = sysinfo + self.compileinfo = compileinfo + self.svnurl = svnurl + self.svnrev = svnrev + self.revrange = revrange + + def __repr__(self): + return 'build.BuildRequest(%r, %r, %r, %r, %r, %r)' % ( + self.email, self.sysinfo, self.compileinfo, self.svnurl, + self.svnrev, self.revrange) + + def serialize(self): + data = {'normalized_rev': self.normalized_rev} + data.update(self.__dict__) + return """\ +email: %(email)s +sysinfo: %(sysinfo)r +compileinfo: %(compileinfo)r +svnurl: %(svnurl)s +svnrev: %(svnrev)s +revrange: %(revrange)s +normalized_rev: %(normalized_rev)s +""" % data + + def _fromstring(cls, s): + data = {} + for line in s.strip().split('\n'): + try: + key, value = line.split(':', 1) + except ValueError: + raise SyntaxError('line %r not in the right format' % (line,)) + data[key.strip()] = value.strip() + ret = cls(data['email'], eval(data['sysinfo']), + eval(data['compileinfo']), data['svnurl'], data['svnrev'], + int(data['revrange'])) + ret._nr = int(data['normalized_rev']) + return ret + fromstring = classmethod(_fromstring) + + def has_satisfying_data(self, other): + """ return True if other request's data satisfies our needs """ + return (self.sysinfo == other.sysinfo and + self.compileinfo == other.compileinfo and + self.svnurl == other.svnurl and + self.rev_in_range(other.normalized_rev)) + + _nr = None + def _normalized_rev(self): + if self._nr is None: + self._nr = normalize_revision(self.svnurl, self.svnrev) + return self._nr + normalized_rev = property(_normalized_rev) + + def rev_in_range(self, comparerev): + return (self.normalized_rev >= comparerev - self.revrange and + self.normalized_rev <= comparerev + self.revrange) + Modified: pypy/dist/pypy/tool/build/client.py ============================================================================== --- pypy/dist/pypy/tool/build/client.py (original) +++ pypy/dist/pypy/tool/build/client.py Wed Dec 13 15:49:47 2006 @@ -20,22 +20,24 @@ self.channel.waitclose() self.channel.close() - def compile(self, info): + def compile(self, request): """send a compile job to the client side""" - self.channel.send(info) + self.channel.send(request.serialize()) accepted = self.channel.receive() if accepted: - self.busy_on = info - thread.start_new_thread(self.wait_until_done, (info,)) + self.busy_on = request + thread.start_new_thread(self.wait_until_done, (request,)) else: - self.refused.append(info) + self.refused.append(request) return accepted - def wait_until_done(self, info): - buildpath = self.server.get_new_buildpath(info) + def wait_until_done(self, request): + buildpath = self.server.get_new_buildpath(request) + open('/tmp/tessie', 'w').write('foo') if not self.testing: fp = buildpath.zipfile.open('w') + gotdata = False try: while True: # read data in chunks @@ -47,13 +49,14 @@ # end of data is marked by sending a None if chunk is None: break + gotdata = True fp.write(chunk) finally: fp.close() # write the log (process stdout/stderr) to the buildpath buildpath.log = self.channel.receive() - self.server.compilation_done(info, buildpath) + self.server.compilation_done(buildpath) self.busy_on = None initcode = """ @@ -142,3 +145,4 @@ def isatty(self): return False + Modified: pypy/dist/pypy/tool/build/config.py ============================================================================== --- pypy/dist/pypy/tool/build/config.py (original) +++ pypy/dist/pypy/tool/build/config.py Wed Dec 13 15:49:47 2006 @@ -37,3 +37,8 @@ # sysinfo, compileinfo), if one of them returns False the compilation will # not be accepted client_checkers = [] + +# function to turn SVN paths into full URLs +def svnpath_to_url(p): + return 'http://codespeak.net/svn/pypy/%s' % (p,) + Modified: pypy/dist/pypy/tool/build/server.py ============================================================================== --- pypy/dist/pypy/tool/build/server.py (original) +++ pypy/dist/pypy/tool/build/server.py Wed Dec 13 15:49:47 2006 @@ -3,6 +3,7 @@ import thread import smtplib import py +from pypy.tool.build.build import BuildPath def issubdict(d1, d2): """sees whether a dict is a 'subset' of another dict @@ -24,129 +25,6 @@ return False return True -class RequestStorage(object): - """simple registry that manages information""" - def __init__(self, info_to_path=[]): - self._id_to_info = {} # id -> info dict - self._id_to_emails = {} # id -> requestor email address - self._id_to_path = {} # id -> filepath - - self._last_id = 0 - self._id_lock = thread.allocate_lock() - - self._build_initial(info_to_path) - - def request(self, email, info): - """place a request - - this either returns a path to the binary (if it's available - already) or an id for the info - """ - infoid = self.get_info_id(info) - path = self._id_to_path.get(infoid) - if path is not None: - return path - self._id_to_emails.setdefault(infoid, []).append(email) - - def get_info_id(self, info): - """retrieve or create an id for an info dict""" - self._id_lock.acquire() - try: - for k, v in self._id_to_info.iteritems(): - if v == info: - return k - self._last_id += 1 - id = self._last_id - self._id_to_info[id] = info - return id - finally: - self._id_lock.release() - - def add_build(self, info, path): - """store the data for a build and make it available - - returns a list of email addresses for the people that should be - warned - """ - infoid = self.get_info_id(info) - emails = self._id_to_emails.pop(infoid) - self._id_to_path[infoid] = path - return emails - - def _build_initial(self, info_to_path): - """fill the dicts with info about files that are already built""" - for info, path in info_to_path: - id = self.get_info_id(info) - self._id_to_path[id] = path - -from py.__.path.local.local import LocalPath -class BuildPath(LocalPath): - def _info(self): - info = getattr(self, '_info_value', []) - if info: - return info - for name in ['system', 'compile']: - currinfo = {} - infopath = self.join('%s_info.txt' % (name,)) - if not infopath.check(): - return ({}, {}) - for line in infopath.readlines(): - line = line.strip() - if not line: - continue - chunks = line.split(':') - key = chunks.pop(0) - value = ':'.join(chunks) - currinfo[key] = eval(value) - info.append(currinfo) - info = tuple(info) - self._info_value = info - return info - - def _set_info(self, info): - self._info_value = info - assert len(info) == 2, 'not a proper info tuple' - for i, name in enumerate(['system', 'compile']): - infopath = self.join('%s_info.txt' % (name,)) - infopath.ensure() - fp = infopath.open('w') - try: - for key, value in info[i].iteritems(): - fp.write('%s: %r\n' % (key, value)) - finally: - fp.close() - - info = property(_info, _set_info) - - def _zipfile(self): - return py.path.local(self / 'data.zip') - - def _set_zipfile(self, iterable): - # XXX not in use right now... - fp = self._zipfile().open('w') - try: - for chunk in iterable: - fp.write(chunk) - finally: - fp.close() - - zipfile = property(_zipfile, _set_zipfile) - - def _log(self): - log = self.join('log') - if not log.check(): - return '' - return log.read() - - def _set_log(self, data): - self.join('log').write(data) - - log = property(_log, _set_log) - - def _done(self): - return not not self.log - done = property(_done) - class PPBServer(object): retry_interval = 10 @@ -161,15 +39,18 @@ self._buildpath = py.path.local(builddir) self._clients = [] - info_to_path = [] + + done = [] for bp in self._get_buildpaths(builddir): if bp.done: - info_to_path.append((bp.info, str(bp))) + done.append(bp) else: # throw away half-done builds... bp.remove() - self._requeststorage = RequestStorage(info_to_path) + + self._done = done self._queued = [] + self._waiting = [] self._queuelock = thread.allocate_lock() self._namelock = thread.allocate_lock() @@ -180,7 +61,7 @@ client, client.sysinfo)) client.channel.send('welcome') - def compile(self, requester_email, info): + def compile(self, request): """start a compilation requester_email is an email address of the person requesting the @@ -197,47 +78,53 @@ in any case, if the first item of the tuple returned is False, an email will be sent once the build is available """ - path = self._requeststorage.request(requester_email, info) - if path is not None: - pathstr = str(path) - self._channel.send('already a build for this info available') - return (True, pathstr) + # store the request, if there's already a build available the + # storage will return that path + for bp in self._done: + if request.has_satisfying_data(bp.request): + path = str(bp) + self._channel.send('already a build for this info available') + return (True, path) for client in self._clients: - if client.busy_on == info: - self._channel.send('build for %r currently in progress' % - (info,)) + if client.busy_on and request.has_satisfying_data(client.busy_on): + self._channel.send('build for %s currently in progress' % + (request,)) + self._waiting.append(request) return (False, 'this build is already in progress') # we don't have a build for this yet, find a client to compile it - if self.run(info): + if self.run(request): return (False, 'found a suitable client, going to build') self._queuelock.acquire() try: - self._queued.append(info) + self._queued.append(request) finally: self._queuelock.release() return (False, 'no suitable client found; your request is queued') - def run(self, info): + def run(self, request): """find a suitable client and run the job if possible""" clients = self._clients[:] # XXX shuffle should be replaced by something smarter obviously ;) random.shuffle(clients) for client in clients: - if (client.busy_on or not issubdict(info[0], client.sysinfo) or - info in client.refused): + # if client is busy, or sysinfos don't match, refuse rightaway, + # else ask client to build it + if (client.busy_on or + not issubdict(request.sysinfo, client.sysinfo) or + request in client.refused): continue else: self._channel.send( - 'going to send compile job with info %r to %s' % ( - info, client + 'going to send compile job for request %s to %s' % ( + request, client ) ) - accepted = client.compile(info) + accepted = client.compile(request) if accepted: return True self._channel.send( - 'no suitable client available for compilation with info %r' % ( - info, + 'no suitable client available for compilation of %s' % ( + request, ) ) @@ -247,20 +134,32 @@ while 1: time.sleep(self.retry_interval) self._cleanup_clients() + self._test_waiting() self._try_queued() - def get_new_buildpath(self, info): + def get_new_buildpath(self, request): path = BuildPath(str(self._buildpath / self._create_filename())) - path.info = info + path.request = request return path - def compilation_done(self, info, path): + def compilation_done(self, buildpath): """client is done with compiling and sends data""" - self._channel.send('compilation done for %r, written to %s' % ( - info, path)) - emails = self._requeststorage.add_build(info, path) - for emailaddr in emails: - self._send_email(emailaddr, info, path) + self._queuelock.acquire() + try: + self._channel.send('compilation done for %s, written to %s' % ( + buildpath.request, buildpath)) + emails = [buildpath.request.email] + self._done.append(buildpath) + waiting = self._waiting[:] + for req in waiting: + if req.has_satisfying_data(buildpath.request): + self._waiting.remove(req) + emails.append(req.email) + for emailaddr in emails: + print 'sending mail to %s' % (emailaddr,) + self._send_email(emailaddr, buildpath) + finally: + self._queuelock.release() def _cleanup_clients(self): self._queuelock.acquire() @@ -274,15 +173,34 @@ finally: self._queuelock.release() + def _test_waiting(self): + """ for each waiting request, see if the compilation is still alive + + if the compilation is dead, the request is moved to self._queued + """ + self._queuelock.acquire() + try: + waiting = self._waiting[:] + for request in waiting: + for client in self._clients: + if request.has_satisfying_data(client.busy_on): + break + else: + self._waiting.remove(request) + self._queued.append(request) + continue + finally: + self._queuelock.release() + def _try_queued(self): self._queuelock.acquire() try: toremove = [] - for info in self._queued: - if self.run(info): - toremove.append(info) - for info in toremove: - self._queued.remove(info) + for request in self._queued: + if self.run(request): + toremove.append(request) + for request in toremove: + self._queued.remove(request) finally: self._queuelock.release() @@ -305,7 +223,7 @@ finally: self._namelock.release() - def _send_email(self, addr, info, path): + def _send_email(self, addr, buildpath): self._channel.send('going to send email to %s' % (addr,)) if self._mailhost is not None: msg = '\r\n'.join([ @@ -314,7 +232,9 @@ 'Subject: %s compilation done' % (self._projname,), '', 'The compilation you requested is done. You can find it at', - str(path), + str(build.path), + '', + buildpath.log, ]) server = smtplib.SMTP(self._mailhost, self._mailport) server.set_debuglevel(0) Modified: pypy/dist/pypy/tool/build/test/fake.py ============================================================================== --- pypy/dist/pypy/tool/build/test/fake.py (original) +++ pypy/dist/pypy/tool/build/test/fake.py Wed Dec 13 15:49:47 2006 @@ -1,4 +1,4 @@ -from pypy.tool.build.server import BuildPath +from pypy.tool.build.build import BuildPath class FakeChannel(object): def __init__(self): @@ -23,11 +23,10 @@ self.busy_on = None self.refused = [] - def compile(self, info): - for k, v in info[0].items(): - self.channel.send('%s: %r' % (k, v)) + def compile(self, request): + self.channel.send(request.serialize()) self.channel.send(None) - self.busy_on = info + self.busy_on = request return True class FakeServer(object): @@ -41,15 +40,15 @@ def register(self, client): self._clients.append(client) - def compilation_done(self, info, data): - self._done.append((info, data)) + def compilation_done(self, ret): + self._done.append(ret) i = 0 - def get_new_buildpath(self, info): + def get_new_buildpath(self, request): name = 'build-%s' % (self.i,) self.i += 1 bp = BuildPath(str(self._builddirpath / name)) - bp.info = info + bp.request = request bp.ensure(dir=1) return bp Added: pypy/dist/pypy/tool/build/test/repo.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/tool/build/test/repo.py Wed Dec 13 15:49:47 2006 @@ -0,0 +1,10 @@ +import py + +def create_temp_repo(reponame): + t = py.test.ensuretemp('build-svnrepo') + repo = t.join(reponame) + ret = py.std.os.system('svnadmin create %r' % (str(repo),)) + if ret: + py.test.skip('could not create temporary svn repository') + return py.path.svnurl('file://%s' % (repo,)) + Added: pypy/dist/pypy/tool/build/test/test_build.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/tool/build/test/test_build.py Wed Dec 13 15:49:47 2006 @@ -0,0 +1,153 @@ +import py +from pypy.tool.build import build +from py.__.misc.cache import AgingCache +from py.__.path.svn import urlcommand +from repo import create_temp_repo + +def setup_module(mod): + # remove nasty cache from py.path.svnurl to allow this to work... + mod._oldcache = urlcommand.SvnCommandPath._lsnorevcache + urlcommand.SvnCommandPath._lsnorevcache = AgingCache(maxentries=1, + maxseconds=0) + +def teardown_module(mod): + urlcommand.SvnCommandPath._lsnorevcache = mod._oldcache + +def test_normalize_revision(): + if py.std.sys.platform.startswith('win'): + py.test.skip('win32 escaping problems with file:// urls') + repo = create_temp_repo('normalize') + repo.ensure('foo', dir=True) + foourl = str(repo.join('foo')) + wc = py.path.svnwc(py.test.ensuretemp('build-svnwc').join('wc-foo')) + wc.checkout(foourl) + ret = build.normalize_revision(foourl, 'HEAD') + assert ret == 1 + + f1 = wc.ensure('file1', file=True, versioned=True) + f1.write('foo') + print wc.status().added + wc.commit('test something') + wc.update() + assert int(wc.status().rev) == 2 + ret = build.normalize_revision(foourl, 'HEAD') + assert ret == 2 + + f2 = wc.ensure('file2', file=True, versioned=True) + f2.write('foo') + wc.commit('test something') + wc.update() + ret = build.normalize_revision(foourl, 'HEAD') + assert ret == 3 + + ret = build.normalize_revision(foourl, 1234) + assert ret == 3 + +def test_buildpath(): + tempdir = py.test.ensuretemp('pypybuilder-buildpath') + bp = build.BuildPath(str(tempdir / 'test')) + assert not bp.check() + bp.log = 'foo' + assert bp.check() + +def test_buildpath_request(): + tempdir = py.test.ensuretemp('pypybuilder-buildpath') + temprepo = create_temp_repo('request') + repodir = temprepo.mkdir('foo') + print str(tempdir) + bp = build.BuildPath(str(tempdir / 'test_request')) + assert bp.request is None + br = build.BuildRequest('foo at bar.com', {'foo': 1}, {'bar': 1}, + str(repodir), 'HEAD', 0) + bp.request = br + assert bp.join('request').check() + assert bp.request.serialize() == br.serialize() + +def test_buildpath_zip(): + tempdir = py.test.ensuretemp('pypybuilder-buildpath') + bp = build.BuildPath(str(tempdir / 'test_zip')) + assert isinstance(bp.zipfile, py.path.local) + bp.zipfile = ['foo', 'bar', 'baz'] + assert bp.zipfile.read() == 'foobarbaz' + +def test_buildpath_log_and_done(): + tempdir = py.test.ensuretemp('pypybuilder-buildpath') + bp = build.BuildPath(str(tempdir / 'test_log')) + log = bp.log + assert not log + assert not bp.done + bp.log = 'log data' + assert bp.log == 'log data' + assert bp.done + +def test_buildrequest_serialize(): + br = build.BuildRequest('foo at bar.com', {'foo': 'bar'}, {'spam': 'eggs'}, + 'file:///foo/bar', 'HEAD', 0) + br._nr = 1 + ser = br.serialize() + assert ser == """\ +email: foo at bar.com +sysinfo: {'foo': 'bar'} +compileinfo: {'spam': 'eggs'} +svnurl: file:///foo/bar +svnrev: HEAD +revrange: 0 +normalized_rev: 1 +""" + assert build.BuildRequest.fromstring(ser).serialize() == ser + + py.test.raises(SyntaxError, 'build.BuildRequest.fromstring("foo")') + py.test.raises(KeyError, 'build.BuildRequest.fromstring("foo: bar")') + +def test_buildrequest_has_satisfying_data(): + if py.std.sys.platform.startswith('win'): + py.test.skip('win32 escaping problems with file:// urls') + + # note that this implicitly tests rev_in_range() too... + + repo = create_temp_repo('satisfying') + testproj = repo.ensure('testproj', dir=True) + + testurl = str(testproj) + + wc = py.path.svnwc(py.test.ensuretemp('satisfying-svnwc')) + wc.checkout(testurl) + + br1 = build.BuildRequest('foo at bar.com', {'foo': 'bar'}, {'spam': 'eggs'}, + testurl, 'HEAD', 0) + + br2 = build.BuildRequest('foo at baz.com', {'foo': 'bar'}, {'spam': 'eggs'}, + testurl, 'HEAD', 0) + assert br2.has_satisfying_data(br1) + + br3 = build.BuildRequest('foo at baz.com', {'foo': 'bar'}, {'spam': 'eggs'}, + testurl, 1, 0) + assert br3.has_satisfying_data(br1) + + # this actually succeeds: because there's no revision 2 yet, + # normalize_revision will return the highest rev (1), which matches + br4 = build.BuildRequest('foo at baz.com', {'foo': 'bar'}, {'spam': 'eggs'}, + testurl, 2, 0) + assert br4.has_satisfying_data(br1) + + foo = wc.ensure('foo', file=True) + foo.add() + wc.commit('commit message') + + # now it should fail... + br5 = build.BuildRequest('foo at baz.com', {'foo': 'bar'}, {'spam': 'eggs'}, + testurl, 2, 0) + assert not br5.has_satisfying_data(br1) + + br6 = build.BuildRequest('foo at baz.com', {'foo': 'bar'}, {'spam': 'eggs'}, + testurl, 2, 1) + assert br6.has_satisfying_data(br1) + + br7 = build.BuildRequest('foo at baz.com', {'foo': 'baz'}, {'spam': 'eggs'}, + testurl, 1, 0) + assert not br7.has_satisfying_data(br1) + + br8 = build.BuildRequest('foo at baz.com', {'foo': 'bar'}, {'spam': 'eggs'}, + testurl + '/baz', 1, 0) + assert not br8.has_satisfying_data(br1) + Modified: pypy/dist/pypy/tool/build/test/test_client.py ============================================================================== --- pypy/dist/pypy/tool/build/test/test_client.py (original) +++ pypy/dist/pypy/tool/build/test/test_client.py Wed Dec 13 15:49:47 2006 @@ -1,5 +1,6 @@ import path from pypy.tool.build import client +from pypy.tool.build import build import py import time import sys @@ -9,7 +10,10 @@ def __init__(self, *args, **kwargs): super(ClientForTests, self).__init__(*args, **kwargs) self._done = [] - + +class BuildRequestForTests(build.BuildRequest): + normalized_rev = 1 + def setup_module(mod): mod.temp = temp = py.test.ensuretemp('pypybuilder-client') mod.svr = svr = FakeServer(temp) @@ -26,27 +30,28 @@ svr.register(c2) def test_compile(): - info = ({'foo': 1}, {'bar': 2}) + nfo = ({'foo': 1}, {'bar': 2}) + br = BuildRequestForTests('foo at bar.com', {'foo': 1}, {'bar': 1}, + 'file:///foo', 'HEAD', 0) c1c.send(True) # notifying we 'accept' the compile - accepted = c1.compile(info) + accepted = c1.compile(br) assert accepted ret = c1.channel.receive() - assert ret == info # this was still in the buffer - assert c1.busy_on == info + assert ret == br.serialize() # this was still in the buffer + assert c1.busy_on.serialize() == br.serialize() c1.channel.send('foo bar') c1.channel.send(None) c1.channel.send('log') # meanwhile the client starts a thread that waits until there's data # available on its own channel, with our FakeChannel it has data rightaway, - # though (the channel out and in are the same, and we just sent 'info' + # though (the channel out and in are the same, and we just sent 'ret' # over the out one) time.sleep(1) done = svr._done.pop() - assert done[0] == info - assert done[1] == (temp / 'build-0') + assert str(done) == str(temp / 'build-0') assert temp.join('build-0/log').read() == 'log' def test_channelwrapper(): @@ -66,11 +71,13 @@ assert c.buffer == ['foo', 'bar', 'baz', None] def test_failed_checker(): - info = ({'foo': 1}, {'bar': 2}) + br = build.BuildRequest('foo at bar.com', {'foo': 1}, {'bar': 2}, + 'file:///foo', 'HEAD', 0) + br._nr = 1 c1c.send(False) # notifying we _don't_ 'accept' the compile - accepted = c1.compile(info) + accepted = c1.compile(br) assert not accepted - assert info in c1.refused + assert br in c1.refused assert c1.busy_on == None def test_output_buffer(): Modified: pypy/dist/pypy/tool/build/test/test_pypybuilder.py ============================================================================== --- pypy/dist/pypy/tool/build/test/test_pypybuilder.py (original) +++ pypy/dist/pypy/tool/build/test/test_pypybuilder.py Wed Dec 13 15:49:47 2006 @@ -1,8 +1,10 @@ import path from pypy.tool.build import client, server, execnetconference from pypy.tool.build import config +from pypy.tool.build import build from pypy.config import config as pypyconfig import py +from repo import create_temp_repo # XXX NOTE: if you encounter failing tests on a slow system, you may want to # increase the sleep interval a bit to see if that helps... @@ -20,11 +22,15 @@ def test_functional_1(): if not py.test.pypybuilder_option.functional: py.test.skip('skipping functional test, use --functional to run it') - + # XXX this one is a bit messy, it's a quick functional test for the whole # system, but for instance contains time.sleep()s to make sure all threads # get the time to perform tasks and such... + repo = create_temp_repo('functional') + repo.mkdir('foo') + foourl = str(repo.join('foo')) + # first initialize a server sgw = py.execnet.PopenGateway() temppath = py.test.ensuretemp('pypybuilder-functional') @@ -55,7 +61,8 @@ sys.path += %r from pypy.tool.build import ppbserver - channel.send(ppbserver.compile(%r, (%r, {}))) + from pypy.tool.build import build + channel.send(ppbserver.compile(%r)) channel.close() """ compgw = py.execnet.PopenGateway() @@ -65,8 +72,9 @@ # freezes (from the app waiting for input) # this one should fail because there's no client found for foo = 3 - compc = compconf.remote_exec(code % (config.testpath, 'foo1 at bar.com', - {'foo': 3})) + br = build.BuildRequest('foo1 at bar.com', {'foo': 3}, {}, foourl, + 1, 0) + compc = compconf.remote_exec(code % (config.testpath, br)) # sorry... py.std.time.sleep(SLEEP_INTERVAL) @@ -76,8 +84,9 @@ assert ret[1].find('no suitable client found') > -1 # this one should be handled by client 1 - compc = compconf.remote_exec(code % (config.testpath, 'foo2 at bar.com', - {'foo': 1})) + br = build.BuildRequest('foo2 at bar.com', {'foo': 1}, {}, foourl, + 1, 0) + compc = compconf.remote_exec(code % (config.testpath, br)) # client 1 will now send a True to the server to tell it wants to compile cc1.send(True) @@ -95,7 +104,8 @@ # client 1 should by now have received the info to build for ret = cc1.receive() - assert ret == ({'foo': 1}, {}) + request = build.BuildRequest.fromstring(ret) + assert request.sysinfo == {'foo': 1} # this should have created a package in the temp dir assert len(temppath.listdir()) == 1 @@ -122,7 +132,7 @@ ppbserver._try_queued() # give the server some time, the clients 'compile' in threads time.sleep(%s) - channel.send(ppbserver._requeststorage._id_to_emails) + channel.send(ppbserver._waiting) channel.close() """ compgw2 = py.execnet.PopenGateway() @@ -134,7 +144,7 @@ # we check whether all emails are now sent, since after adding the third # client, and calling _try_queued(), both jobs should have been processed ret = compc2.receive() - assert ret.values() == [] + assert ret == [] # this should also have created another package in the temp dir assert len(temppath.listdir()) == 2 @@ -152,3 +162,4 @@ compgw.exit() compgw2.exit() sgw.exit() + Modified: pypy/dist/pypy/tool/build/test/test_server.py ============================================================================== --- pypy/dist/pypy/tool/build/test/test_server.py (original) +++ pypy/dist/pypy/tool/build/test/test_server.py Wed Dec 13 15:49:47 2006 @@ -2,9 +2,9 @@ from pypy.tool.build import server import py from fake import FakeChannel, FakeClient -from pypy.tool.build.server import RequestStorage -from pypy.tool.build.server import BuildPath +from pypy.tool.build import build import time +from repo import create_temp_repo def setup_module(mod): mod.temppath = temppath = py.test.ensuretemp('pypybuilder-server') @@ -45,44 +45,55 @@ py.test.raises(IndexError, 'svr._channel.receive()') def test_compile(): - # XXX this relies on the output not changing... quite scary - info = {'foo': 1} - ret = svr.compile('test at domain.com', (info, None)) + repo = create_temp_repo('compile') + repodir = repo.mkdir('foo') + + br = build.BuildRequest('foo at bar.com', {'foo': 1}, {}, + str(repodir), 'HEAD', 0) + ret = svr.compile(br) assert not ret[0] assert ret[1].find('found a suitable client') > -1 ret = svr._channel.receive() assert ret.find('going to send compile job') > -1 ret = c1.channel.receive() - assert ret == 'foo: 1' - ret = c1.channel.receive() - assert ret is None + assert ret == br.serialize() + none = c1.channel.receive() + assert none is None py.test.raises(IndexError, "c2.channel.receive()") - svr.compile('test at domain.com', ({'foo': 3}, None)) + br2 = build.BuildRequest('foo at baz.com', {'foo': 3}, {}, + str(repodir), 'HEAD', 0) + svr.compile(br2) ret = svr._channel.receive() assert ret.find('no suitable client available') > -1 - info = {'bar': [3]} - svr.compile('test at domain.com', (info, None)) + br3 = build.BuildRequest('foo at qux.com', {'bar': [3]}, {}, + str(repodir), 'HEAD', 0) + svr.compile(br3) ret = svr._channel.receive() assert ret.find('going to send') > -1 - assert c2.channel.receive() == 'bar: [3]' + assert c2.channel.receive() == br3.serialize() assert c2.channel.receive() is None py.test.raises(IndexError, "c1.channel.receive()") - info = {'foo': 1} - ret = svr.compile('test at domain.com', (info, None)) + br4 = build.BuildRequest('foo at spam.com', {'foo': 1}, {}, + str(repodir), 'HEAD', 0) + ret = svr.compile(br4) assert not ret[0] assert ret[1].find('this build is already') > -1 assert svr._channel.receive().find('currently in progress') > -1 c1.busy_on = None - bp = BuildPath(str(temppath / 'foo')) - svr.compilation_done((info, None), bp) - ret = svr.compile('test at domain.com', (info, None)) + bp = build.BuildPath(str(temppath / 'foo')) + print br + bp.request = br + svr.compilation_done(bp) + clone = build.BuildRequest.fromstring(bp.request.serialize()) + clone.email = 'test at domain.com' + ret = svr.compile(clone) assert ret[0] assert isinstance(ret[1], str) - assert BuildPath(ret[1]) == bp + assert build.BuildPath(ret[1]) == bp ret = svr._channel.receive() assert ret.find('compilation done for') > -1 for i in range(2): @@ -90,22 +101,6 @@ assert ret.find('going to send email to') > -1 ret = svr._channel.receive() assert ret.find('already a build for this info') > -1 - -def test_buildpath(): - tempdir = py.test.ensuretemp('pypybuilder-buildpath') - # grmbl... local.__new__ checks for class equality :( - bp = BuildPath(str(tempdir / 'test1')) - assert not bp.check() - assert bp.info == ({}, {}) - - bp.info = ({'foo': 1, 'bar': [1,2]}, {'baz': 1}) - assert bp.info == ({'foo': 1, 'bar': [1,2]}, {'baz': 1}) - assert (sorted((bp / 'system_info.txt').readlines()) == - ['bar: [1, 2]\n', 'foo: 1\n']) - - assert isinstance(bp.zipfile, py.path.local) - bp.zipfile = ['foo', 'bar', 'baz'] - assert bp.zipfile.read() == 'foobarbaz' def test__create_filename(): svr._i = 0 # reset counter @@ -113,37 +108,42 @@ name1 = svr._create_filename() assert name1 == 'pypytest-%s-0' % (today,) assert svr._create_filename() == ('pypytest-%s-1' % (today,)) - bp = BuildPath(str(temppath / ('pypytest-%s-2' % (today,)))) + bp = build.BuildPath(str(temppath / ('pypytest-%s-2' % (today,)))) try: bp.ensure() assert svr._create_filename() == 'pypytest-%s-3'% (today,) finally: bp.remove() - + def test_get_new_buildpath(): + repo = create_temp_repo('get_new_buildpath') + repodir = repo.mkdir('foo') + svr._i = 0 today = time.strftime('%Y%m%d') + br = build.BuildRequest('foo at bar.com', {'foo': 'bar'}, {'baz': 'qux'}, + str(repodir), 'HEAD', 0) - path1 = svr.get_new_buildpath(({'foo': 'bar'}, {'baz': 'qux'})) + bp1 = svr.get_new_buildpath(br) + bp1.log = ['foo'] try: - assert isinstance(path1, BuildPath) - assert path1.info == ({'foo': 'bar'}, {'baz': 'qux'}) - assert path1.basename == 'pypytest-%s-0' % (today,) + assert isinstance(bp1, build.BuildPath) + assert bp1.basename == 'pypytest-%s-0' % (today,) try: - path2 = svr.get_new_buildpath(({'foo': 'baz'}, {'bar': 'qux'})) - assert path2.info == ({'foo': 'baz'}, {'bar': 'qux'}) - assert path2.basename == 'pypytest-%s-1' % (today,) + bp2 = svr.get_new_buildpath(br) + bp2.log = ['bar'] + assert bp2.basename == 'pypytest-%s-1' % (today,) finally: - path2.remove() + bp2.remove() finally: - path1.remove() + bp1.remove() def test_cleanup_old_builds(): temppath = py.test.ensuretemp('cleanup_old_builds') - bp1 = server.BuildPath(temppath.join('bp1')) + bp1 = build.BuildPath(temppath.join('bp1')) bp1.ensure(dir=True) - bp2 = server.BuildPath(temppath.join('bp2')) + bp2 = build.BuildPath(temppath.join('bp2')) bp2.ensure(dir=True) bp2.log = 'log' svr = server.PPBServer('test', FakeChannel(), str(temppath)) Added: pypy/dist/pypy/tool/build/tooloption.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/tool/build/tooloption.py Wed Dec 13 15:49:47 2006 @@ -0,0 +1,14 @@ +import py +from pypy.config.config import StrOption, IntOption +from pypy.config.config import OptionDescription, Config + +import sys +tool_optiondescription = OptionDescription('tool', '', [ + IntOption('svnrev', 'Subversion revision', default='HEAD'), + StrOption('svnpath', 'Subversion path (relative to the project root)', + default='dist'), + StrOption('revrange', 'Revision range (max difference in revision between ' + 'requested build and result)', default=0), +]) + +tool_config = Config(tool_optiondescription) From guido at codespeak.net Wed Dec 13 16:26:59 2006 From: guido at codespeak.net (guido at codespeak.net) Date: Wed, 13 Dec 2006 16:26:59 +0100 (CET) Subject: [pypy-svn] r35680 - in pypy/dist/pypy/tool/build: . bin builds test Message-ID: <20061213152659.03B4D1007C@code0.codespeak.net> Author: guido Date: Wed Dec 13 16:26:57 2006 New Revision: 35680 Removed: pypy/dist/pypy/tool/build/builds/ Modified: pypy/dist/pypy/tool/build/ (props changed) pypy/dist/pypy/tool/build/bin/client pypy/dist/pypy/tool/build/config.py pypy/dist/pypy/tool/build/test/test_pypybuilder.py Log: Some cleanups (e.g. builds is now removed and added to svn:ignore), added checker for svn url (to not have the clients do checkouts of other stuff), moved compilation to a function (should become sandboxed later to allow importing from a freshly updated pypy checkout). Modified: pypy/dist/pypy/tool/build/bin/client ============================================================================== --- pypy/dist/pypy/tool/build/bin/client (original) +++ pypy/dist/pypy/tool/build/bin/client Wed Dec 13 16:26:57 2006 @@ -5,7 +5,6 @@ import random import traceback from pypy.tool.build import config as buildconfig -from pypy.interpreter.error import OperationError from py.execnet import SshGateway, PopenGateway from pypy.tool.build.client import init, zip_result, OutputBuffer @@ -13,6 +12,7 @@ from pypy.config.config import to_optparse, Config from pypy.config import pypyoption +from pypy.interpreter.error import OperationError from pypy.translator.goal import targetpypystandalone from pypy.translator.driver import TranslationDriver from pypy.tool.udir import udir @@ -27,6 +27,12 @@ path=buildconfig.path, port=buildconfig.port) +def compile(config): + driver = TranslationDriver.from_targetspec( + targetpypystandalone.__dict__, config=config, + default_goal='compile') + driver.proceed(['compile']) + print channel.receive() # welcome message try: try: @@ -50,8 +56,13 @@ ) accepting = True for checker in buildconfig.client_checkers: - if not checker(request.sysinfo, request.compileinfo): - print 'request refused by checker', checker.func_name + if not checker(request): + if hasattr(checker, 'im_func'): + name = '%s.%s' % (checker.im_class.__name__, + checker.im_func.func_name) + else: + name = checer.func_name + print 'request refused by checker', name accepting = False break channel.send(accepting) @@ -67,16 +78,11 @@ sys.stdout = buffer sys.stderr = buffer exception_occurred = False + try: try: - driver = TranslationDriver.from_targetspec( - targetpypystandalone.__dict__, config=config, - default_goal='compile') - driver.proceed(['compile']) + compile(config) except Exception, e: - if isinstance(e, OperationError): - print dir(e) - print repr(e.msg) exception_occurred = True exc, e, tb = sys.exc_info() print '=' * 79 Modified: pypy/dist/pypy/tool/build/config.py ============================================================================== --- pypy/dist/pypy/tool/build/config.py (original) +++ pypy/dist/pypy/tool/build/config.py Wed Dec 13 16:26:57 2006 @@ -33,12 +33,23 @@ # settings for the tests testpath = [str(py.magic.autopath().dirpath().dirpath())] -# when considering a compile job, the checkers below will be called (args -# sysinfo, compileinfo), if one of them returns False the compilation will +# this var is only used below +svnroot = 'http://codespeak.net/svn/pypy' + +# when considering a compile job, the checkers below will be called (with +# request as only arg), if one of them returns False the compilation will # not be accepted -client_checkers = [] +def check_svnroot(req): + if not req.svnurl.startswith(svnroot): + return False + return True + +client_checkers = [check_svnroot] # function to turn SVN paths into full URLs def svnpath_to_url(p): - return 'http://codespeak.net/svn/pypy/%s' % (p,) + root = svnroot + if root.endswith('/'): + root = root[:-1] + return '%s/%s' % (root, p) Modified: pypy/dist/pypy/tool/build/test/test_pypybuilder.py ============================================================================== --- pypy/dist/pypy/tool/build/test/test_pypybuilder.py (original) +++ pypy/dist/pypy/tool/build/test/test_pypybuilder.py Wed Dec 13 16:26:57 2006 @@ -23,6 +23,8 @@ if not py.test.pypybuilder_option.functional: py.test.skip('skipping functional test, use --functional to run it') + config.checkers = [] + # XXX this one is a bit messy, it's a quick functional test for the whole # system, but for instance contains time.sleep()s to make sure all threads # get the time to perform tasks and such... From antocuni at codespeak.net Wed Dec 13 17:17:49 2006 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Wed, 13 Dec 2006 17:17:49 +0100 (CET) Subject: [pypy-svn] r35682 - in pypy/dist/pypy: objspace/std translator/goal Message-ID: <20061213161749.71DBD1007A@code0.codespeak.net> Author: antocuni Date: Wed Dec 13 17:17:47 2006 New Revision: 35682 Modified: pypy/dist/pypy/objspace/std/multimethod.py pypy/dist/pypy/translator/goal/targetpypystandalone.py Log: (antocuni, fed by arigo and pedronis) Select the multimethod installer depending on the typesystem. Added a sanity check to be sure not to mix the two installers. Modified: pypy/dist/pypy/objspace/std/multimethod.py ============================================================================== --- pypy/dist/pypy/objspace/std/multimethod.py (original) +++ pypy/dist/pypy/objspace/std/multimethod.py Wed Dec 13 17:17:47 2006 @@ -101,12 +101,15 @@ class InstallerVersion1: """NOT_RPYTHON""" + instance_counter = 0 + mmfunccache = {} prefix_memo = {} def __init__(self, multimethod, prefix, list_of_typeorders, baked_perform_call=True, base_typeorder=None): + self.__class__.instance_counter += 1 self.multimethod = multimethod # avoid prefix clashes, user code should supply different prefixes # itself for nice names in tracebacks @@ -602,11 +605,13 @@ class InstallerVersion2(object): """NOT_RPYTHON""" + instance_counter = 0 mrdtables = {} def __init__(self, multimethod, prefix, list_of_typeorders, baked_perform_call=True, base_typeorder=None): #print 'InstallerVersion2:', prefix + self.__class__.instance_counter += 1 self.multimethod = multimethod self.prefix = prefix self.list_of_typeorders = list_of_typeorders Modified: pypy/dist/pypy/translator/goal/targetpypystandalone.py ============================================================================== --- pypy/dist/pypy/translator/goal/targetpypystandalone.py (original) +++ pypy/dist/pypy/translator/goal/targetpypystandalone.py Wed Dec 13 17:17:47 2006 @@ -2,13 +2,6 @@ import os, sys -# as of revision 27081, multimethod.py uses the InstallerVersion1 by default -# because it is much faster both to initialize and run on top of CPython. -# The InstallerVersion2 is optimized for making a translator-friendly -# structure. So we patch here... -from pypy.objspace.std import multimethod -multimethod.Installer = multimethod.InstallerVersion2 - from pypy.objspace.std.objspace import StdObjSpace from pypy.interpreter import gateway from pypy.interpreter.error import OperationError @@ -88,7 +81,21 @@ return parser def handle_config(self, config): - pass + # as of revision 27081, multimethod.py uses the InstallerVersion1 by default + # because it is much faster both to initialize and run on top of CPython. + # The InstallerVersion2 is optimized for making a translator-friendly + # structure for low level backends. However, InstallerVersion1 is still + # preferable for high level backends, so we patch here. + from pypy.objspace.std import multimethod + if config.translation.type_system == 'lltype': + assert multimethod.InstallerVersion1.instance_counter == 0,\ + 'The wrong Installer version has already been instatiated' + multimethod.Installer = multimethod.InstallerVersion2 + else: + # don't rely on the default, set again here + assert multimethod.InstallerVersion2.instance_counter == 0,\ + 'The wrong Installer version has already been instatiated' + multimethod.Installer = multimethod.InstallerVersion1 def handle_translate_config(self, translateconfig): pass From arigo at codespeak.net Wed Dec 13 17:44:57 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 13 Dec 2006 17:44:57 +0100 (CET) Subject: [pypy-svn] r35683 - pypy/dist/pypy/doc Message-ID: <20061213164457.C3A6810088@code0.codespeak.net> Author: arigo Date: Wed Dec 13 17:44:56 2006 New Revision: 35683 Modified: pypy/dist/pypy/doc/draft-jit-outline.txt Log: A bit more introduction & terminology... Modified: pypy/dist/pypy/doc/draft-jit-outline.txt ============================================================================== --- pypy/dist/pypy/doc/draft-jit-outline.txt (original) +++ pypy/dist/pypy/doc/draft-jit-outline.txt Wed Dec 13 17:44:56 2006 @@ -71,7 +71,79 @@ thought as a generalisation of polymorphic inline caches XXX ref. -Hint-Annotation and Compile Time Values +Terminology +========================================= + +Partial evaluation is the process of evaluating a function, say ``f(x, +y)``, with only partial information about the value of its arguments, +say the value of the ``x`` argument only. This produces a *residual* +function ``g(y)``, which takes less arguments than the original - only +the information not specified during the partial evaluation process need +to be provided to the residual function, in this example the ``y`` +argument. + +Partial evaluation (PE) comes in two flavors: + +* *On-line* PE: a compiler-like algorithm takes the source code of the + function ``f(x, y)`` (or its intermediate representation, i.e. its + control flow graph in PyPy's terminology), and some partial + information, e.g. ``x = 5``. From this, it produces the residual + function ``g(y)`` directly, by following in which operations the + knowledge ``x = 5`` can be used, which loops can be unrolled, etc. + +* *Off-line* PE: in many cases, the goal of partial evaluation is to + improve performance in a specific application. Assume that we have a + single known function ``f(x, y)`` in which we think that the value of + ``x`` will change slowly during the execution of our program - much + more slowly than the value of ``y``. An obvious example is a loop + that calls ``f(x, y)`` many times with always the same value ``x``. + We could then use an on-line partial evaluator to produce a ``g(y)`` + for each new value of ``x``. In practice, the overhead of the partial + evaluator might be too large for it to be executed at run-time. + Howeer, if we know the function ``f`` in advance, and if we know + *which* arguments are the ones that we will want to partially evaluate + ``f`` with, then we do not need a full compiler-like analysis of ``f`` + every time the value of ``x`` changes. We can precompute off-line a + specialized function ``f1(x)``, which when called produces a residual + function ``g(y)``. + +Off-line partial evaluation is based on *binding-time analysis*, which +is the process of determining among the variables used in a function (or +a set of function) which ones are going to be known in advance and which +ones are not. In the above example, such an analysis would be able to +infer that the constantness of the argument ``x`` implies the +constantness of many intermediate values used in the function. The +*binding time* of a variable determines how early the value of the +variable will be known. + +The PyPy JIT is essentially an off-line partial evaluator. As such, +there are three distinct phases: + +* *Translation time*: during the normal translation of an RPython + program like PyPy, we perform binding-time analysis and off-line + specialization. This produces a new set of functions (``f1(x)`` in + our running example) which are linked with the rest of the program, as + described in Timeshifting_. + +* *Compile time*: during the execution of the program, when a new value + for ``x`` is found, ``f1(x)`` is invoked. All the computations + performed by ``f1(x)`` are called compile-time computations. This is + justified by the fact that ``f1(x)`` is in some sense a compiler, + whose sole effect is to produce residual code. + +* *Run time*: the normal execution of the program. + +The binding-time terminology that we are using in PyPy is based on the +colors that we use when displaying the control flow graphs: + +* *Green* variables are values that are known at compile-time - + e.g. ``x``. + +* *Red* variables are values that are not known until run-time - + e.g. ``y``. + + +Binding-time analysis ========================================= Hint annotator and hint(concrete=True)... @@ -85,6 +157,8 @@ blue containers... +.. _timeshifting: + Timeshifting: transforming interpreter into compilers ====================================================== From pedronis at codespeak.net Wed Dec 13 17:55:12 2006 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Wed, 13 Dec 2006 17:55:12 +0100 (CET) Subject: [pypy-svn] r35684 - pypy/dist/pypy/doc Message-ID: <20061213165512.196B610088@code0.codespeak.net> Author: pedronis Date: Wed Dec 13 17:55:09 2006 New Revision: 35684 Modified: pypy/dist/pypy/doc/draft-jit-outline.txt Log: typos and small fixes. Modified: pypy/dist/pypy/doc/draft-jit-outline.txt ============================================================================== --- pypy/dist/pypy/doc/draft-jit-outline.txt (original) +++ pypy/dist/pypy/doc/draft-jit-outline.txt Wed Dec 13 17:55:09 2006 @@ -100,7 +100,7 @@ We could then use an on-line partial evaluator to produce a ``g(y)`` for each new value of ``x``. In practice, the overhead of the partial evaluator might be too large for it to be executed at run-time. - Howeer, if we know the function ``f`` in advance, and if we know + However, if we know the function ``f`` in advance, and if we know *which* arguments are the ones that we will want to partially evaluate ``f`` with, then we do not need a full compiler-like analysis of ``f`` every time the value of ``x`` changes. We can precompute off-line a @@ -109,14 +109,14 @@ Off-line partial evaluation is based on *binding-time analysis*, which is the process of determining among the variables used in a function (or -a set of function) which ones are going to be known in advance and which +a set of functions) which ones are going to be known in advance and which ones are not. In the above example, such an analysis would be able to infer that the constantness of the argument ``x`` implies the constantness of many intermediate values used in the function. The *binding time* of a variable determines how early the value of the variable will be known. -The PyPy JIT is essentially an off-line partial evaluator. As such, +The PyPy JIT is generated using off-line partial evaluation. As such, there are three distinct phases: * *Translation time*: during the normal translation of an RPython @@ -136,10 +136,10 @@ The binding-time terminology that we are using in PyPy is based on the colors that we use when displaying the control flow graphs: -* *Green* variables are values that are known at compile-time - +* *Green* variables contain values that are known at compile-time - e.g. ``x``. -* *Red* variables are values that are not known until run-time - +* *Red* variables contain values that are not known until run-time - e.g. ``y``. From ericvrp at codespeak.net Wed Dec 13 18:00:33 2006 From: ericvrp at codespeak.net (ericvrp at codespeak.net) Date: Wed, 13 Dec 2006 18:00:33 +0100 (CET) Subject: [pypy-svn] r35686 - pypy/dist/pypy/jit/codegen/i386/test Message-ID: <20061213170033.6A16D10084@code0.codespeak.net> Author: ericvrp Date: Wed Dec 13 18:00:31 2006 New Revision: 35686 Modified: pypy/dist/pypy/jit/codegen/i386/test/test_operation.py Log: i386 backend support for passing and returning c_floats (used by llvm backend) Modified: pypy/dist/pypy/jit/codegen/i386/test/test_operation.py ============================================================================== --- pypy/dist/pypy/jit/codegen/i386/test/test_operation.py (original) +++ pypy/dist/pypy/jit/codegen/i386/test/test_operation.py Wed Dec 13 18:00:31 2006 @@ -7,7 +7,7 @@ from pypy.jit.codegen.i386.rgenop import RI386GenOp from pypy.rpython.memory.lltypelayout import convert_offset_to_int from pypy.rlib.rarithmetic import r_uint -from ctypes import cast, c_void_p, CFUNCTYPE, c_int +from ctypes import cast, c_void_p, CFUNCTYPE, c_int, c_float from pypy import conftest def conv(n): @@ -48,7 +48,13 @@ class BasicTests(object): - def rgen(self, ll_function, argtypes): + @staticmethod + def _to_ctypes(t): #limited type support for now + if t is float: + return c_float + return c_int + + def rgen(self, ll_function, argtypes, rettype=int): #XXX get rettype from annotation t = TranslationContext() t.buildannotator().build_types(ll_function, argtypes) t.buildrtyper().specialize() @@ -58,8 +64,9 @@ rgenop = self.RGenOp() self.rgenop = rgenop # keep this alive! gv_generated = graph2rgenop.compile_graph(rgenop, graph) - ctypestypes = [c_int] * len(argtypes) # for now - fp = cast(c_void_p(gv_generated.value), CFUNCTYPE(c_int, *ctypestypes)) + ctypestypes = [BasicTests._to_ctypes(t) for t in argtypes] + fp = cast(c_void_p(gv_generated.value), + CFUNCTYPE(BasicTests._to_ctypes(rettype), *ctypestypes)) return fp def test_arithmetic(self): @@ -147,7 +154,7 @@ def test_char_array(self): A = lltype.GcArray(lltype.Char) def fn(n): - a = lltype.malloc(A, 5) + a = lltype.malloc(A, 5) #XXX this boils down to rgenop.genop_malloc_varsize() ? a[4] = 'H' a[3] = 'e' a[2] = 'l' @@ -226,23 +233,37 @@ assert fp(25, 3) == fn(25, 3) def test_float_arithmetic(self): - for fn in [lambda x, y: bool(y), - lambda x, y: bool(y - 2.0), - lambda x, y: x + y, + for fn in [lambda x, y: x + y, lambda x, y: x - y, lambda x, y: x * y, lambda x, y: x / y, - #lambda x, y: x % y, not used? - lambda x, y: x ** y, + #lambda x, y: x % y, #not used? lambda x, y: -y, - lambda x, y: ~y, + #lambda x, y: ~y, #TypeError: bad operand type for unary ~ lambda x, y: abs(y), lambda x, y: abs(-x), ]: - fp = self.rgen(fn, [float, float]) + fp = self.rgen(fn, [float, float], float) assert fp(40.0, 2.0) == fn(40.0, 2.0) assert fp(25.125, 1.5) == fn(25.125, 1.5) + def test_float_pow(self): #harder test for llvm + for fn in [lambda x, y: x ** y, #not supported in llvm backend + ]: + fp = self.rgen(fn, [float, float], float) + assert fp(40.0, 2.0) == fn(40.0, 2.0) + assert fp(25.125, 1.5) == fn(25.125, 1.5) + + def test_float_cast(self): #because of differnt rettype + for fn in [lambda x: bool(x), + lambda x: bool(x - 2.0), + ]: + fp = self.rgen(fn, [float], bool) + assert fp(6.0) == fn(6.0) + assert fp(2.0) == fn(2.0) + assert fp(0.0) == fn(0.0) + assert fp(-2.0) == fn(-2.0) + class TestBasic(I386TestBasicMixin, BasicTests): From ericvrp at codespeak.net Wed Dec 13 18:06:02 2006 From: ericvrp at codespeak.net (ericvrp at codespeak.net) Date: Wed, 13 Dec 2006 18:06:02 +0100 (CET) Subject: [pypy-svn] r35687 - in pypy/dist/pypy/jit/codegen/llvm: . test Message-ID: <20061213170602.9CFB210093@code0.codespeak.net> Author: ericvrp Date: Wed Dec 13 18:06:01 2006 New Revision: 35687 Modified: pypy/dist/pypy/jit/codegen/llvm/conftest.py pypy/dist/pypy/jit/codegen/llvm/rgenop.py pypy/dist/pypy/jit/codegen/llvm/test/test_llvmjit.py pypy/dist/pypy/jit/codegen/llvm/test/test_operation.py Log: Quite a few fixes and additions to the llvm jit backend. - float arithmetic (apart from pow()) passes - calling gc_malloc_fnaddr() works - op_get/setarrayitem kind of work (well enought for those tests to pass) - added py.test options --lineno, --print-debug and --print-source - fix operations that needed to be told what the returntype was Modified: pypy/dist/pypy/jit/codegen/llvm/conftest.py ============================================================================== --- pypy/dist/pypy/jit/codegen/llvm/conftest.py (original) +++ pypy/dist/pypy/jit/codegen/llvm/conftest.py Wed Dec 13 18:06:01 2006 @@ -15,3 +15,18 @@ # py.test.skip('detected a %r CPU' % (processor,)) # # return super(Directory, self).run() + +Option = py.test.Config.Option + +option = py.test.Config.addoptions("llvm options", + Option('--lineno', action="store_true", default=False, + dest="lineno", + help="add linenumbers to the generated code"), + + Option('--print-source', action="store_true", default=False, + dest="print_source", + help="print generated sources"), + + Option('--print-debug', action="store_true", default=False, + dest="print_debug", + help="print debug information")) Modified: pypy/dist/pypy/jit/codegen/llvm/rgenop.py ============================================================================== --- pypy/dist/pypy/jit/codegen/llvm/rgenop.py (original) +++ pypy/dist/pypy/jit/codegen/llvm/rgenop.py Wed Dec 13 18:06:01 2006 @@ -5,10 +5,18 @@ from pypy.jit.codegen.model import GenVar, GenConst, CodeGenSwitch from pypy.jit.codegen.llvm import llvmjit from pypy.rlib.objectmodel import we_are_translated +from pypy.jit.codegen.i386.rgenop import gc_malloc_fnaddr + + +from pypy.jit.codegen.llvm.conftest import option + +LINENO = option.lineno +PRINT_SOURCE = option.print_source +PRINT_DEBUG = option.print_debug def log(s): - if not we_are_translated(): + if PRINT_DEBUG and not we_are_translated(): print str(s) @@ -61,12 +69,18 @@ class BoolConst(GenericConst): - type = 'int' + type = 'bool' class CharConst(GenericConst): type = 'ubyte' + def __init__(self, value): + if type(value) is str: + self.value = ord(value) + else: + self.value = value + class UniCharConst(GenericConst): type = 'int' @@ -289,19 +303,22 @@ @specialize.arg(1) def genop1(self, opname, gv_arg): - #log('%s Builder.genop1' % self.block.label) + log('%s Builder.genop1 %s %s' % ( + self.block.label, opname, gv_arg.operand())) genmethod = getattr(self, 'op_' + opname) return genmethod(gv_arg) @specialize.arg(1) def genop2(self, opname, gv_arg1, gv_arg2): - #log('%s Builder.genop2' % self.block.label) + log('%s Builder.genop2 %s %s,%s' % ( + self.block.label, opname, gv_arg1.operand(), gv_arg2.operand())) genmethod = getattr(self, 'op_' + opname) return genmethod(gv_arg1, gv_arg2) - def _rgenop2_generic(self, llvm_opcode, gv_arg1, gv_arg2, restype='int'): + def _rgenop2_generic(self, llvm_opcode, gv_arg1, gv_arg2, restype=None): log('%s Builder._rgenop2_generic %s %s,%s' % ( self.block.label, llvm_opcode, gv_arg1.operand(), gv_arg2.operand2())) + restype = restype or gv_arg1.type gv_result = Var(restype) self.asm.append(' %s=%s %s,%s' % ( gv_result.operand2(), llvm_opcode, gv_arg1.operand(), gv_arg2.operand2())) @@ -335,13 +352,16 @@ op_uint_add = op_float_add = op_int_add op_uint_sub = op_float_sub = op_int_sub op_uint_mul = op_float_mul = op_int_mul - op_uint_floordiv = op_float_floordiv = op_int_floordiv + op_uint_floordiv = op_int_floordiv op_uint_mod = op_int_mod op_uint_and = op_int_and op_uint_or = op_int_or op_uint_xor = op_int_xor op_uint_lshift = op_int_lshift op_uint_rshift = op_int_rshift + + def op_float_truediv(self, gv_x, gv_y): return self._rgenop2_generic('fdiv', gv_x, gv_y) + def op_float_neg(self, gv_x): return self._rgenop2_generic('sub', FloatConst(0.0), gv_x) def op_int_lt(self, gv_x, gv_y): return self._rgenop2_generic('setlt', gv_x, gv_y, 'bool') def op_int_le(self, gv_x, gv_y): return self._rgenop2_generic('setle', gv_x, gv_y, 'bool') @@ -357,9 +377,10 @@ op_char_gt = op_uint_gt = op_float_gt = op_int_gt op_char_ge = op_uint_ge = op_float_ge = op_int_ge - def _rgenop1_generic(self, llvm_opcode, gv_x, restype='int'): + def _rgenop1_generic(self, llvm_opcode, gv_x, restype=None): log('%s Builder._rgenop1_generic %s %s' % ( self.block.label, llvm_opcode, gv_x.operand())) + restype = restype or gv_x.type gv_result = Var(restype) self.asm.append(' %s=%s %s' % ( gv_result.operand2(), llvm_opcode, gv_x.operand())) @@ -369,19 +390,25 @@ def op_int_invert(self, gv_x): return self._rgenop2_generic('xor', gv_x, IntConst(-1)) def op_uint_invert(self, gv_x): return self._rgenop2_generic('xor', gv_x, UIntConst((1<<32)-1)) - def op_int_abs(self, gv_x): + def _abs(self, gv_x, nullstr='0'): gv_comp = Var('bool') gv_abs_pos = Var(gv_x.type) gv_result = Var(gv_x.type) - self.asm.append(' %s=setgt %s,-1' % (gv_comp.operand2(), gv_x.operand())) - self.asm.append(' %s=sub %s 0,%s' % (gv_abs_pos.operand2(), gv_x.type, gv_x.operand2())) + self.asm.append(' %s=setge %s,%s' % ( + gv_comp.operand2(), gv_x.operand(), nullstr)) + self.asm.append(' %s=sub %s %s,%s' % ( + gv_abs_pos.operand2(), gv_x.type, nullstr, gv_x.operand2())) self.asm.append(' %s=select %s,%s,%s' % ( gv_result.operand2(), gv_comp.operand(), gv_x.operand(), gv_abs_pos.operand())) return gv_result + op_int_abs = _abs + def op_float_abs(self, gv_x): return self._abs(gv_x, '0.0') + #def op_bool_not(self, gv_x): #use select, xor or sub XXXX todo: did not see a test for this - def _cast_to(self, gv_x, restype='int'): + def _cast_to(self, gv_x, restype=None): + restype = restype or gv_x.type gv_result = Var(restype) self.asm.append(' %s=cast %s to %s' % ( gv_result.operand2(), gv_x.operand(), restype)) @@ -484,8 +511,98 @@ def op_float_is_true(self, gv_x): return self._is_true(gv_x, '0.0') + def genop_getarrayitem(self, arraytoken, gv_ptr, gv_index): + #XXX what about non char arrays? + log('%s Builder.genop_getarrayitem %s,%s,%s' % ( + self.block.label, arraytoken, gv_ptr, gv_index)) + gv_result = Var('ubyte') + gv_p = Var(gv_result.type+'*') #XXX get this from arraytoken + self.asm.append(' %s=getelementptr [0x%s]* %s,int 0,%s' % ( + gv_p.operand2(), gv_result.type, gv_ptr.operand2(), gv_index.operand())) + self.asm.append(' %s=load %s' % ( + gv_result.operand2(), gv_p.operand())) + return gv_result + + def genop_getarraysubstruct(self, arraytoken, gv_ptr, gv_index): + ''' + self.mc.MOV(edx, gv_ptr.operand(self)) + op = self.itemaddr(edx, arraytoken, gv_index) + self.mc.LEA(eax, op) + return self.returnvar(eax) + ''' + #XXX TODO + gv_result = Var('int') + log('%s Builder.genop_getarraysubstruct %s,%s,%s' % ( + self.block.label, arraytoken, gv_ptr, gv_index)) + self.asm.append(' %s=int 0 ;%s Builder.genop_getarraysubstruct %s,%s,%s' % ( + gv_result.operand2(), self.block.label, arraytoken, gv_ptr, gv_index)) + return gv_result + + def genop_getarraysize(self, arraytoken, gv_ptr): + ''' + lengthoffset, startoffset, itemoffset = arraytoken + self.mc.MOV(edx, gv_ptr.operand(self)) + return self.returnvar(mem(edx, lengthoffset)) + ''' + #XXX TODO + gv_result = Var('int') + log('%s Builder.genop_getarraysize %s,%s' % ( + self.block.label, arraytoken, gv_ptr)) + self.asm.append(' %s=int 0 ;%s Builder.genop_getarraysize %s,%s' % ( + gv_result.operand2(), self.block.label, arraytoken, gv_ptr)) + return gv_result + + def genop_setarrayitem(self, arraytoken, gv_ptr, gv_index, gv_value): + #XXX what about non char arrays? + log('%s Builder.genop_setarrayitem %s,%s,%s,%s' % ( + self.block.label, arraytoken, gv_ptr, gv_index, gv_value)) + gv_p = Var('ubyte*') #XXX get this from arraytoken + self.asm.append(' %s=getelementptr [0x%s]* %s,int 0,%s' % ( + gv_p.operand2(), gv_ptr.type[:-1], gv_ptr.operand2(), gv_index.operand())) + self.asm.append(' store %s,%s' % ( + gv_value.operand(), gv_p.operand())) + + def genop_malloc_fixedsize(self, size): + ''' + # XXX boehm only, no atomic/non atomic distinction for now + self.push(imm(size)) + self.mc.CALL(rel32(gc_malloc_fnaddr())) + return self.returnvar(eax) + ''' + log('%s Builder.genop_malloc_fixedsize %s' % ( + self.block.label, size)) + gv_result = Var('ubyte*') + gv_gc_malloc_fnaddr = Var('[0xubyte]* (int)*') + #XXX or use addGlobalFunctionMapping in libllvmjit.restart() + self.asm.append(' %s=cast int %d to %s ;gc_malloc_fnaddr' % ( + gv_gc_malloc_fnaddr.operand2(), gc_malloc_fnaddr(), gv_gc_malloc_fnaddr.type)) + self.asm.append(' %s=call %s(int %d)' % ( + gv_result.operand2(), gv_gc_malloc_fnaddr.operand(), size)) + return gv_result + def genop_malloc_varsize(self, varsizealloctoken, gv_size): - gv_result = Var('sbyte') #XXX TODO + ''' + # XXX boehm only, no atomic/non atomic distinction for now + # XXX no overflow checking for now + op_size = self.itemaddr(None, varsizealloctoken, gv_size) + self.mc.LEA(edx, op_size) + self.push(edx) + self.mc.CALL(rel32(gc_malloc_fnaddr())) + lengthoffset, _, _ = varsizealloctoken + self.mc.MOV(ecx, gv_size.operand(self)) + self.mc.MOV(mem(eax, lengthoffset), ecx) + return self.returnvar(eax) + ''' + log('%s Builder.genop_malloc_varsize %s,%s' % ( + self.block.label, varsizealloctoken, gv_size)) + gv_result = Var('ubyte*') + gv_gc_malloc_fnaddr = Var('[0xubyte]* (int)*') + #XXX or use addGlobalFunctionMapping in libllvmjit.restart() + self.asm.append(' %s=cast int %d to %s ;gc_malloc_fnaddr' % ( + gv_gc_malloc_fnaddr.operand2(), gc_malloc_fnaddr(), gv_gc_malloc_fnaddr.type)) + self.asm.append(' %s=call %s(%s)' % ( + gv_result.operand2(), gv_gc_malloc_fnaddr.operand(), gv_size.operand())) + #XXX TODO set length field return gv_result def genop_call(self, sigtoken, gv_fnptr, args_gv): @@ -493,10 +610,10 @@ self.block.label, sigtoken, gv_fnptr, [v.operand() for v in args_gv])) argtypes, restype = sigtoken gv_returnvar = Var(restype) - #XXX we probably need to call an address directly if we can't resolve the funcname + #XXX we probably need to call an address directly if we can't resolve the funcsig self.asm.append(' %s=call %s(%s)' % ( gv_returnvar.operand2(), - self.rgenop.funcname[gv_fnptr.value], + self.rgenop.funcsig[gv_fnptr.value], ','.join([v.operand() for v in args_gv]))) return gv_returnvar @@ -530,27 +647,29 @@ class RLLVMGenOp(object): #changed baseclass from (AbstractRGenOp) for better error messages - funcname = {} #HACK for looking up function names given a pre/post compilation function pointer + funcsig = {} #HACK for looking up function signatures funcused = {} #we rename functions when encountered multiple times (for test_branching_compile) def end(self): - log('RLLVMGenOp.end') + log(' RLLVMGenOp.end') self.blocklist.append(EpilogueBlock()) asmlines = [] for block in self.blocklist: block.writecode(asmlines) - asmlines.append('') + if LINENO: + asmlines = ['%s ;%d' % (asmlines[i], i+1) for i in range(len(asmlines))] asm_string = '\n'.join(asmlines) self.blocklist = None - log(asm_string) + if PRINT_SOURCE: + print asm_string llvmjit.parse(asm_string) llvmjit.transform(3) #optimize module (should be on functions actually) function = llvmjit.getNamedFunction(self.name) entrypoint = llvmjit.getPointerToFunctionAsInt(function) # XXX or directly cast the ctypes ptr to int with: # ctypes.cast(ptr, c_void_p).value - self.funcname[entrypoint] = self.funcname[self.gv_entrypoint.value] + self.funcsig[entrypoint] = self.funcsig[self.gv_entrypoint.value] self.gv_entrypoint.value = entrypoint # ---------------------------------------------------------------- @@ -563,7 +682,7 @@ else: self.funcused[name] = 0 - log('RLLVMGenOp.newgraph %s,%s' % (sigtoken, name)) + log(' RLLVMGenOp.newgraph %s,%s' % (sigtoken, name)) prologueblock = PrologueBlock(sigtoken, name) self.blocklist = [prologueblock] @@ -571,9 +690,9 @@ prologueblock.startblocklabel = builder.nextlabel argtypes, restype = sigtoken - n = len(self.funcname) * 2 + 1 #+1 so we recognize these pre compilation 'pointers' + n = len(self.funcsig) * 2 + 1 #+1 so we recognize these pre compilation 'pointers' self.name = name - self.funcname[n] = '%s %%%s' % (restype, name) + self.funcsig[n] = '%s %%%s' % (restype, name) self.gv_entrypoint = IntConst(n) #note: updated by Builder.end() (i.e after compilation) args = list(prologueblock.inputargs) builder.enter_next_block(argtypes, args) Modified: pypy/dist/pypy/jit/codegen/llvm/test/test_llvmjit.py ============================================================================== --- pypy/dist/pypy/jit/codegen/llvm/test/test_llvmjit.py (original) +++ pypy/dist/pypy/jit/codegen/llvm/test/test_llvmjit.py Wed Dec 13 18:06:01 2006 @@ -136,12 +136,6 @@ llvmjit.restart() assert execute(llsquare, 'square', 4) == 4 * 4 -def test_execute_with_ctypes(): - py.test.skip('TODO: implement execute with ctypes thru real pointer to function') - llvmjit.restart() - #should use function.getPointerToFunction - assert execute(llsquare, 'square', 4) == 4 * 4 - def test_execute_nothing(): llvmjit.restart() assert llvmjit.execute(None, 4) == -1 #-1 == no function supplied Modified: pypy/dist/pypy/jit/codegen/llvm/test/test_operation.py ============================================================================== --- pypy/dist/pypy/jit/codegen/llvm/test/test_operation.py (original) +++ pypy/dist/pypy/jit/codegen/llvm/test/test_operation.py Wed Dec 13 18:06:01 2006 @@ -5,11 +5,12 @@ skip_unsupported_platform() -#py.test.skip('WIP') + class LLVMTestBasicMixin(object): RGenOp = RLLVMGenOp + class TestBasic(LLVMTestBasicMixin, BasicTests): @@ -19,35 +20,6 @@ def skip(self): py.test.skip('WIP') - #test_unsigned = skip - #XXX -r_uint(n) generated op_int_sub(0,n) , why not op_uint_sub? - # -AR- for me it crashes on the 'x%y' test. The LLVM ref manual - # seems to mention only 'srem' and 'urem' instructions and - # not 'rem'. Same for 'sdiv' and 'udiv' and no 'div'. - # Strange, the translator/llvm backend seems to produce - # 'div' and 'rem' anyway... - # -ER- the langref on llvm.org seems to be for the upcoming llvm version 2.0 - # -AR- I see in llvm.rgenop that op_uint_invert uses an IntConst - # (should be UIntConst). - # -ER- indeed - - test_float_arithmetic = skip - #XXX bool(f - 2.0) generated op_float_sub(f,IntConst(2)) , why not FloatConst(2.0) ? - # E assert fp(40.0, 2.0) == fn(40.0, 2.0) - # > ArgumentError: argument 1: exceptions.TypeError: int expected instead of float instance - - # [/mnt/hdb3/projects.eric/pypy-dist/pypy/jit/codegen/i386/test/test_operation.py:240] - # -AR- the ctypes function type need to be fixed in rgen() in - # i386.test.test_operation. For now it assumes that all args are - # c_int. The llvm.rgenop.genconst() method should have more cases - # instead of always returning IntConst for any Primitive type; - # e.g. return UIntConst for unsigned integer types, FloatConst for - # float types, and possibly things like CharConst UniCharConst etc. - # based on what T is (the same kind of checks as in kindToken()) - # -ER- extended genconst() - - test_char_array = skip - test_char_varsize_array = skip + test_float_pow = skip test_unichar_array = skip test_char_unichar_fields = skip - From stephan at codespeak.net Wed Dec 13 18:22:40 2006 From: stephan at codespeak.net (stephan at codespeak.net) Date: Wed, 13 Dec 2006 18:22:40 +0100 (CET) Subject: [pypy-svn] r35689 - in pypy/dist/pypy: lib module/_stackless/test Message-ID: <20061213172240.7679C1008F@code0.codespeak.net> Author: stephan Date: Wed Dec 13 18:22:38 2006 New Revision: 35689 Added: pypy/dist/pypy/lib/stackless_old.py pypy/dist/pypy/module/_stackless/test/test_stackless_pickling.py Modified: pypy/dist/pypy/lib/stackless.py pypy/dist/pypy/module/_stackless/test/test_stackless.py Log: new lib/stackless.py. It passes all tests in test_stackless, but the interface is not complete compared to stackless python (the old stackless module was not complete as well). This stackless implementation is not using the 'finished' method from 'interp_coroutine'. this stackless module can be used with plain CPython and a thin wrapper around greenlets. Modified: pypy/dist/pypy/lib/stackless.py ============================================================================== --- pypy/dist/pypy/lib/stackless.py (original) +++ pypy/dist/pypy/lib/stackless.py Wed Dec 13 18:22:38 2006 @@ -6,261 +6,100 @@ import traceback import sys -try: - deadtask = set() -except NameError: - from sets import Set as set - deadtask = set() - - -switches = 0 - from _stackless import coroutine, greenlet +from collections import deque -__all__ = 'run getcurrent getmain schedule tasklet \ - channel TaskletExit coroutine greenlet'.split() +__all__ = 'run getcurrent getmain schedule tasklet channel coroutine \ + TaskletExit greenlet'.split() -main_tasklet = main_coroutine = None -scheduler = None -channel_hook = None -schedlock = False -_schedule_fasthook = None -_schedule_hook = None +global_task_id = 0 +squeue = None +main_tasklet = None +main_coroutine = None +first_run = False class TaskletExit(Exception):pass -def SETNEXT(obj, val): - "this function just makes debugging a bit easier :-)" - obj.next = val - -def SETPREV(obj, val): - "just for debugging" - obj.prev = val - -def SETNONE(obj): - "just for debugging" - obj.prev = obj.next = None - -def SWAPVAL(task1, task2): - "just for debugging" - assert task1 is not None - assert task2 is not None - task1.tempval, task2.tempval = task2.tempval, task1.tempval - -def SETVAL(task, val): - "just for debugging" - assert task is not None - task.tempval = val - -last_task_id = 0 - -def restore_exception(etype, value, stack): - """until I find out how to restore an exception on python level""" - #sys.excepthook(etype, value, stack) - raise etype, value, stack - #raise etype(value) - -class TaskletProxy(object): - """TaskletProxy is needed to give the main_coroutine tasklet behaviour""" - def __init__(self, coro): - self.alive = True - self.atomic = False - self.blocked = 0 - self.block_trap = False - self.frame = None - self.ignore_nesting = False - self.is_current = False - self.is_main = False - self.nesting_level = 0 - self.next = self.prev = None - self.paused = False - self.recursion_depth = 0 - self.restorable = False - self.scheduled = False - self.task_id = 0 - self.tempval = None - self._coro = coro - - def __repr__(self): - return tasklet.__str__(self) - - __str__ = __repr__ - - def __getattr__(self,attr): - return getattr(self._coro,attr) - - def __reduce__(self): - return getmain, () - -class bomb(object): - """ - A bomb object is used to hold exceptions in tasklets. - Whenever a tasklet is activated and its tempval is a bomb, - it will explode as an exception. - - You can create a bomb by hand and attach it to a tasklet if you like. - Note that bombs are 'sloppy' about the argument list, which means that - the following works, although you should use '*sys.exc_info()'. - - from stackless import *; import sys - t = tasklet(lambda:42)() - try: 1/0 - except: b = bomb(sys.exc_info()) - - t.tempval = b - nt.run() # let the bomb explode - """ - - traceback = None - type = None - value = None - - def __init__(self,etype=None, value=None, traceback=None): - self.type = etype - self.value = value - self.traceback = traceback - - def _explode(self): - restore_exception(self.type, self.value, self.traceback) - -def make_deadlock_bomb(): - return bomb(RuntimeError, - RuntimeError("Deadlock: the last runnable tasklet cannot be blocked."), - None) - -def curexc_to_bomb(): - return bomb(*sys.exc_info()) - -def enable_softswitch(flag): - """ - enable_softswitch(flag) -- control the switching behavior. - Tasklets can be either switched by moving C stack slices around - or by avoiding stack changes at all. The latter is only possible - in the top interpreter level. Switching it off is for timing and - debugging purposes. This flag exists once for the whole process. - For inquiry only, use the phrase - ret = enable_softswitch(0); enable_softswitch(ret) - By default, soft switching is enabled. - - This is not implemented yet!!!! - """ - pass - -def get_thread_info(task_id): - """ - get_thread_info(task_id) -- return a 3-tuple of the thread's - main tasklet, current tasklet and runcount. - To obtain a list of all thread infos, use - - map (stackless.get_thread_info, stackless.threads) - - This is not implemented yet!!!! - """ - pass - -def set_channel_callback(callable): +class channel(object): """ - set_channel_callback(callable) -- install a callback for channels. - Every send/receive action will call the callback function. - Example: - def channel_cb(channel, tasklet, sending, willblock): - ... - sending and willblock are booleans. - Pass None to switch monitoring off again. - """ - global channel_hook - - channel_hook = callable - -def _schedule_callback(prev, next): - global _schedule_hook - return _schedule_hook(prev, next) - -def set_schedule_callback(func): - """ - set_schedule_callback(callable) -- install a callback for scheduling. - Every explicit or implicit schedule will call the callback function - right before the switch is actually done. - Example: - def schedule_cb(prev, next): - ... - When a tasklet is dying, next is None. - When main starts up or after death, prev is None. - Pass None to switch monitoring off again. - """ - global _schedule_fasthook - global _schedule_hook - global _schedule_callback - - if func is not None and not callable(func): - raise TypeError("schedule callback nust be callable") - _schedule_hook = func - if func is None: - _schedule_fasthook = None - else: - _schedule_fasthook = _schedule_callback - -def run(timeout=0): + A channel object is used for communication between tasklets. + By sending on a channel, a tasklet that is waiting to receive + is resumed. If there is no waiting receiver, the sender is suspended. + By receiving from a channel, a tasklet that is waiting to send + is resumed. If there is no waiting sender, the receiver is suspended. """ - run_watchdog(timeout) -- run tasklets until they are all - done, or timeout instructions have passed. Tasklets must - provide cooperative schedule() calls. - If the timeout is met, the function returns. - The calling tasklet is put aside while the tasklets are running. - It is inserted back after the function stops, right before the - tasklet that caused a timeout, if any. - If an exception occours, it will be passed to the main tasklet. - Please note that the 'timeout' feature is not yet implemented - """ - me = scheduler.current_remove() - if me is not main_tasklet: - raise RuntimeError("run() must be run from the main thread's \ - main tasklet") - return scheduler.schedule_task(me, scheduler._head) + def __init__(self): + self.balance = 0 + self.closing = False + self.queue = deque() -def getcurrent(): - """ - getcurrent() -- return the currently executing tasklet. - """ + def __str__(self): + return 'channel(%s,%s)' % (self.balance, self.queue) - curr = coroutine.getcurrent() - if curr is main_coroutine: - return main_tasklet - else: - return curr + def close(self): + """ + channel.close() -- stops the channel from enlarging its queue. + + If the channel is not empty, the flag 'closing' becomes true. + If the channel is empty, the flag 'closed' becomes true. + """ + self.closing = True -def getmain(): - return main_tasklet + @property + def closed(self): + return self.closing and not self.queue -def _do_schedule(retval=None, remove=False): - prev = scheduler._head - next = prev.next - if remove: - scheduler.current_remove() - ret = scheduler.schedule_task(prev, next) - if retval is None: - return ret - else: - return retval + def open(self): + """ + channel.open() -- reopen a channel. See channel.close. + """ + self.closing = False -def schedule_remove(retval=None): - """ - schedule(retval=stackless.current) -- switch to the next runnable tasklet. - The return value for this call is retval, with the current - tasklet as default. - schedule_remove(retval=stackless.current) -- ditto, and remove self. - """ - return _do_schedule(retval, True) + def receive(self): + """ + channel.receive() -- receive a value over the channel. + If no other tasklet is already sending on the channel, + the receiver will be blocked. Otherwise, the receiver will + continue immediately, and the sender is put at the end of + the runnables list. + The above policy can be changed by setting channel flags. + """ + receiver = getcurrent() + if self.balance > 0: # somebody is already sending + self.balance -= 1 + sender = self.queue.popleft() + #receiver.tempval = sender.tempval + receiver.tempval = sender.tempval + squeue.append(sender) + else: # nobody is waiting + self.balance -= 1 + squeue.pop() + self.queue.append(receiver) + schedule() + msg = receiver.tempval + return msg -def schedule(retval=None): - """ - schedule(retval=stackless.current) -- switch to the next runnable tasklet. - The return value for this call is retval, with the current - tasklet as default. - schedule_remove(retval=stackless.current) -- ditto, and remove self. - """ - return _do_schedule(retval, False) + def send(self, msg): + """ + channel.send(value) -- send a value over the channel. + If no other tasklet is already receiving on the channel, + the sender will be blocked. Otherwise, the receiver will + be activated immediately, and the sender is put at the end of + the runnables list. + """ + sender = getcurrent() + sender.tempval = msg + if self.balance < 0: # somebody is already waiting + receiver = self.queue.popleft() + self.balance += 1 + receiver.tempval = msg + squeue.appendleft(receiver) + schedule() + else: # nobody is waiting + self.queue.append(squeue[-1]) + self.balance += 1 + schedule_remove() class tasklet(coroutine): """ @@ -269,55 +108,28 @@ New tasklets can be created with methods from the stackless module. """ - __slots__ = ['alive','atomic','blocked','block_trap','frame', - 'ignore_nesting','is_current','is_main', - 'nesting_level','next','paused','prev','recursion_depth', - 'restorable','scheduled','tempval','task_id'] - def __new__(cls, func=None): return super(tasklet,cls).__new__(cls) def __init__(self, func=None): - global last_task_id - super(tasklet,self).__init__() + super(tasklet, self).__init__() + self._init(func) + + def _init(self, func=None): + global global_task_id + self.tempval = func self.alive = False - self.atomic = False - self.blocked = 0 - self.block_trap = False - self.frame = None - self.ignore_nesting = False - self.is_current = False - self.is_main = False - self.nesting_level = 0 - self.next = self.prev = None - self.paused = False - self.recursion_depth = 0 - self.restorable = False - self.scheduled = False - last_task_id += 1 - self.task_id = last_task_id - self.tempval = None - if func is not None: - self.bind(func) + self.task_id = global_task_id + global_task_id += 1 - def __call__(self, *argl, **argd): - self.setup(*argl, **argd) - return self + def __str__(self): + return '' % \ + (self.task_id, self.is_alive, self.is_zombie) - def __repr__(self): - next = None - if self.next is not None: - next = self.next.task_id - prev = None - if self.prev is not None: - prev = self.prev.task_id - if self.blocked: - bs = 'b' - else: - bs = '-' - return 'T%s(%s) (%s, %s)' % (self.task_id, bs, next, prev) + __repr__ = __str__ - __str__ = __repr__ + def __call__(self, *argl, **argd): + return self.setup(*argl, **argd) def bind(self, func): """ @@ -329,20 +141,7 @@ """ if not callable(func): raise TypeError('tasklet function must be a callable') - SETVAL(self, func) - - def insert(self): - """ - Insert this tasklet at the end of the scheduler list, - given that it isn't blocked. - Blocked tasklets need to be reactivated by channels. - """ - if self.blocked: - raise RuntimeError('You cannot run a blocked tasklet') - if self.is_zombie: - raise RuntimeError('You cannot run an unbound(dead) tasklet') - if self.next is None: - scheduler.current_insert(self) + self.tempval = func def kill(self): """ @@ -354,94 +153,7 @@ """ if not self.is_zombie: coroutine.kill(self) - return self.raise_exception(TaskletExit, TaskletExit()) - - def raise_exception(self, exc, value): - """ - tasklet.raise_exception(exc, value) -- raise an exception for the - tasklet. exc must be a subclass of Exception. - The tasklet is immediately activated. - """ - b = bomb(exc, value) - SETVAL(self, b) - return scheduler.schedule_task(getcurrent(), self) - - def remove(self): - """ - Removing a tasklet from the runnables queue. - Note: If this tasklet has a non-trivial C stack attached, - it will be destructed when the containing thread state is destroyed. - Since this will happen in some unpredictable order, it may cause - unwanted side-effects. Therefore it is recommended to either run - tasklets to the end or to explicitly kill() them. - """ - scheduler.current_remove(self) - - def run(self): - """ - Run this tasklet, given that it isn't blocked. - Blocked tasks need to be reactivated by channels. - """ - scheduler.schedule_task(getcurrent(), self) - - def set_atomic(self, val): - """ - t.set_atomic(flag) -- set tasklet atomic status and return current one. - If set, the tasklet will not be auto-scheduled. - This flag is useful for critical sections which should not be - interrupted. - usage: - tmp = t.set_atomic(1) - # do critical stuff - t.set_atomic(tmp) - Note: Whenever a new tasklet is created, the atomic flag is initialized - with the atomic flag of the current tasklet.Atomic behavior is - additionally influenced by the interpreter nesting level. - See set_ignore_nesting. - """ - tmpval = self.atomic - self.atomic = val - return tmpval - - def set_ignore_nesting(self, flag): - """ - t.set_ignore_nesting(flag) -- set tasklet ignore_nesting status and - return current one. If set, the tasklet may be auto-scheduled, - even if its nesting_level is > 0. - This flag makes sense if you know that nested interpreter levels are - safe for auto-scheduling. This is on your own risk, handle with care! - usage: - tmp = t.set_ignore_nesting(1) - # do critical stuff - t.set_ignore_nesting(tmp) - - Please note that this piece of code does effectively nothing. - """ - tmpval = self.ignore_nesting - self.ignore_nesting = flag - return tmpval - - def finished(self, excinfo): - """called, when coroutine is finished. This gives the tasklet - a chance to clean up after himself.""" - - if self.alive: self.alive = False - if self.next is not self: - next = self.next - else: - next = getmain() - scheduler.remove_task(self) - deadtask.add(self) - prev = self - if excinfo[0] is not None: - et = excinfo[0] - ev = excinfo[1] - tr = excinfo[2] - b = bomb(et, et(ev), tr) - next = getmain() - SETVAL(next, b) - scheduler.schedule_task(prev, next) def setup(self, *argl, **argd): """ @@ -450,429 +162,140 @@ if self.tempval is None: raise TypeError('cframe function must be callable') coroutine.bind(self,self.tempval,*argl,**argd) - SETVAL(self, None) + self.tempval = None self.alive = True - self.insert() + squeue.append(self) + return self def __reduce__(self): - # xxx save more one, two, three = coroutine.__reduce__(self) assert one is coroutine assert two == () - return tasklet, (), (three, self.alive, self.tempval) + return tasklet, () (three, self.alive, self.tempval) def __setstate__(self, (coro_state, alive, tempval)): coroutine.__setstate__(self, coro_state) self.alive = alive self.tempval = tempval -def channel_callback(chan, task, sending, willblock): - return channel_hook(chan, task, sending, willblock) - -class channel(object): +def getmain(): """ - A channel object is used for communication between tasklets. - By sending on a channel, a tasklet that is waiting to receive - is resumed. If there is no waiting receiver, the sender is suspended. - By receiving from a channel, a tasklet that is waiting to send - is resumed. If there is no waiting sender, the receiver is suspended. + getmain() -- return the main tasklet. """ + return main_tasklet - def __init__(self): - self.balance = 0 - self.closing = False - self.preference = -1 - self.next = self.prev = self - self.schedule_all = False - self.task_id = -2 - - def __str__(self): - parts = ['%s' % x.task_id for x in self._content()] - return 'channel(' + str(self.balance) + '): ['+' -> '.join(parts)+']' - - def _get_closed(self): - return self.closing and self.next is None - - closed = property(_get_closed) - - def _channel_insert(self, task, d): - self._ins(task) - self.balance += d - task.blocked = d - - def _content(self): - visited = set((self,)) - items = [] - next = self.next - if next is not self: - while next is not None and next not in visited: - items.append(next) - visited.add(next) - next = next.next - return items - - def _queue(self): - if self.next is self: - return None - else: - return self.next - - def _channel_remove(self, d): - ret = self.next - assert isinstance(ret, (tasklet, TaskletProxy)) - self.balance -= d - self._rem(ret) - ret.blocked = 0 - - return ret - - def channel_remove_specific(self, d, task): - # note: we assume that the task is in the channel - self.balance -= d - self._rem(task) - task.blocked = 0 - - return task - - def _ins(self, task): - if (task.next is not None) or (task.prev is not None): - raise AssertionError('task.next and task.prev must be None') - # insert at end - SETPREV(task, self.prev) - SETNEXT(task, self) - SETNEXT(self.prev, task) - SETPREV(self, task) - - def _rem(self, task): - assert task.next is not None - assert task.prev is not None - #remove at end - SETPREV(task.next, task.prev) - SETNEXT(task.prev, task.next) - SETNONE(task) - - def _notify(self, task, d, cando, res): - global schedlock - global channel_hook - if channel_hook is not None: - if schedlock: - raise RuntimeError('Recursive channel call due to callbacks!') - schedlock = 1 - channel_callback(self, task, d > 0, not cando) - schedlock = 0 - - def _channel_action(self, arg, d, stackl): - source = scheduler._head - target = self.next - assert source is getcurrent() - interthread = 0 # no interthreading at the moment - if d > 0: - cando = self.balance < 0 - else: - cando = self.balance > 0 - - assert abs(d) == 1 - SETVAL(source, arg) - if not interthread: - self._notify(source, d, cando, None) - if cando: - # communication 1): there is somebody waiting - target = self._channel_remove(-d) - SWAPVAL(source, target) - if interthread: - raise Exception('no interthreading: I can not be reached...') - else: - if self.schedule_all: - scheduler.current_insert(target) - target = source.next - elif self.preference == -d: - scheduler._set_head(source.next) - scheduler.current_insert(target) - scheduler._set_head(source) - else: - scheduler.current_insert(target) - target = source - else: - # communication 2): there is nobody waiting - if source.block_trap: - raise RuntimeError("this tasklet does not like to be blocked") - if self.closing: - raise StopIteration() - scheduler.current_remove() - self._channel_insert(source, d) - target = scheduler._head - retval = scheduler.schedule_task(source, target) - if interthread: - self._notify(source, d, cando, None) - return retval - - def close(self): - """ - channel.close() -- stops the channel from enlarging its queue. - - If the channel is not empty, the flag 'closing' becomes true. - If the channel is empty, the flag 'closed' becomes true. - """ - self.closing = True - - def next(self): - """ - x.next() -> the next value, or raise StopIteration - """ - if self.closing and not self.balance: - raise StopIteration() - yield self.receive() - - def open(self): - """ - channel.open() -- reopen a channel. See channel.close. - """ - self.closing = False - - def receive(self): - """ - channel.receive() -- receive a value over the channel. - If no other tasklet is already sending on the channel, - the receiver will be blocked. Otherwise, the receiver will - continue immediately, and the sender is put at the end of - the runnables list. - The above policy can be changed by setting channel flags. - """ - return self._channel_action(None, -1, 1) - - def send(self, msg): - """ - channel.send(value) -- send a value over the channel. - If no other tasklet is already receiving on the channel, - the sender will be blocked. Otherwise, the receiver will - be activated immediately, and the sender is put at the end of - the runnables list. - """ - return self._channel_action(msg, 1, 1) - - def send_exception(self, exc, value): - """ - channel.send_exception(exc, value) -- send an exception over the - channel. exc must be a subclass of Exception. - Behavior is like channel.send, but that the receiver gets an exception. - """ - b = bomb(exc, value) - self.send(bomb) +def getcurrent(): + """ + getcurrent() -- return the currently executing tasklet. + """ - def send_sequence(self, value): - """ - channel.send_sequence(seq) -- sed a stream of values - over the channel. Combined with a generator, this is - a very efficient way to build fast pipes. - """ - for item in value: - self.send(item) + curr = coroutine.getcurrent() + if curr is main_coroutine: + return main_tasklet + else: + return curr -class Scheduler(object): - """The singleton Scheduler. Provides mostly scheduling convenience - functions. In normal circumstances, scheduler._head point the - current running tasklet. _head and current_tasklet might be - out of sync just before the actual task switch takes place.""" +def run(): + """ + run_watchdog(timeout) -- run tasklets until they are all + done, or timeout instructions have passed. Tasklets must + provide cooperative schedule() calls. + If the timeout is met, the function returns. + The calling tasklet is put aside while the tasklets are running. + It is inserted back after the function stops, right before the + tasklet that caused a timeout, if any. + If an exception occours, it will be passed to the main tasklet. - def __init__(self): - self._set_head(getcurrent()) + Please note that the 'timeout' feature is not yet implemented + """ + schedule_remove() + +scall = 0 - def _cleanup(self, task): - task.alive = False - self.remove_task(task) - if self._head is None: - self.current_insert(main_tasklet) - self.schedule_task(getcurrent(), self._head) - - def _set_head(self, task): - self._head = task - - def reset(self): - self.__init__() - - def __len__(self): - return len(self._content()) - - def _content(self): - "convenience method to get the tasklets that are in the queue" - visited = set() - items = [] - next = self._head - if next is not self: - while next is not None and next not in visited: - items.append(next) - visited.add(next) - next = next.next - return items +def schedule_remove(retval=None): + """ + schedule(retval=stackless.current) -- switch to the next runnable tasklet. + The return value for this call is retval, with the current + tasklet as default. + schedule_remove(retval=stackless.current) -- ditto, and remove self. + """ + global first_run + if first_run: + squeue.rotate(-1) + first_run = False + t = squeue.pop() + if t is not getcurrent(): + squeue.appendleft(t) - def __str__(self): - parts = ['%s' % x.task_id for x in self._content()] - if self._head is not self: - currid = self._head.task_id - else: - currid = -1 - return 'Scheduler: [' + ' -> '.join(parts) + ']' - - def _chain_insert(self, task): - assert task.next is None - assert task.prev is None - if self._head is None: - SETNEXT(task, task) - SETPREV(task, task) - self._set_head(task) - else: - r = self._head - l = r.prev - SETNEXT(l, task) - SETPREV(r, task) - SETPREV(task, l) - SETNEXT(task, r) - - def remove_task(self, task): - l = task.prev - r = task.next - SETNEXT(l, r) - SETPREV(r, l) - self._set_head(r) - if r == task: - self._set_head(None) - SETNONE(task) - - return task - - def _chain_remove(self): - if self._head is None: - return None - return self.remove_task(self._head) - - def current_insert(self, task): - "insert 'task' at end of running queue" - self._chain_insert(task) - - def current_insert_after(self, task): - "insert 'task' just after the current one" - if self._head is not None: - curr = self._head - self._set_head(curr.next) - self._chain_insert(task) - self._set_head(curr) - else: - self.current_insert(task) - - def current_remove(self): - "remove current tasklet from queue" - return self._chain_remove() - - def channel_remove_slow(self, task): - prev = task.prev - while not isinstance(prev, channel): - prev = prev.prev - chan = prev - assert chan.balance - if chan.balance > 0: - d = 1 - else: - d = -1 - return chan.channel_remove_specific(d, task) - - def bomb_explode(self, task): - thisbomb = task.tempval - assert isinstance(thisbomb, bomb) - SETVAL(task, None) - thisbomb._explode() -# try: -# thisbomb._explode() -# finally: -# if getcurrent() == main_tasklet: -# sys.excepthook(thisbomb.type, -# thisbomb.value, -# thisbomb.traceback) -# sys.exit() - - def _notify_schedule(self, prev, next, errflag): - if _schedule_fasthook is not None: - global schedlock - if schedlock: - raise RuntimeError('Recursive scheduler call due to callbacks!') - schedlock = True - ret = _schedule_fasthook(prev, next) - schedlock = False - if ret: - return errflag - - def schedule_task_block(self, prev): - if main_tasklet.next is None: - if isinstance(prev.tempval, bomb): - SETVAL(main_tasklet, prev.tempval) - return self.schedule_task(prev, main_tasklet) - retval = make_deadlock_bomb() - SETVAL(prev, retval) - - return self.schedule_task(prev, prev) - - def schedule_task(self, prev, next): - global switches - switches += 1 - myswitch = switches - if next is None: - return self.schedule_task_block(prev) - if next.blocked: - self.channel_remove_slow(next) - self.current_insert(next) - elif next.next is None: - self.current_insert(next) - if prev is next: - retval = prev.tempval - if isinstance(retval, bomb): - self.bomb_explode(prev) - return retval - self._notify_schedule(prev, next, None) - self._set_head(next) - - try: - res = next.switch() - except: - pass - - for dead in tuple(deadtask): - deadtask.discard(dead) - - # the code below should work, but doesn't - - #if not dead.is_zombie: - # coroutine.kill(dead) - # del dead - - retval = prev.tempval - if isinstance(retval, bomb): - self.bomb_explode(prev) - - return retval - - def schedule_callback(self, prev, next): - ret = _schedule_hook(prev, next) - if ret: - return 0 - else: - return -1 + schedule() - def __reduce__(self): - if self is scheduler: - return _return_sched, (), () +def schedule(retval=None): + """ + schedule(retval=stackless.current) -- switch to the next runnable tasklet. + The return value for this call is retval, with the current + tasklet as default. + schedule_remove(retval=stackless.current) -- ditto, and remove self. + """ -def _return_sched(): - return scheduler + mtask = getmain() + global first_run + if first_run: + squeue.rotate(-1) + first_run = False + + if squeue: + task = squeue[0] + squeue.rotate(-1) + if task is not getcurrent() and task.is_alive: + task.switch() + curr = getcurrent() + if not task.is_alive: + if squeue: + pt = squeue.pop() + if pt.is_alive: + squeue.append(pt) + else: + coroutine.kill(task) + else: + if curr is not mtask: + mtask.switch() + schedule() -def __init(): +def _init(): global main_tasklet - global main_coroutine - global scheduler - main_coroutine = c = coroutine.getcurrent() - main_tasklet = TaskletProxy(c) - SETNEXT(main_tasklet, main_tasklet) - SETPREV(main_tasklet, main_tasklet) - main_tasklet.is_main = True - scheduler = Scheduler() - -__init() + global global_task_id + global first_run + global squeue + first_run = True + global_task_id = 0 + main_tasklet = coroutine.getcurrent() + try: + main_tasklet.__class__ = tasklet + except TypeError: # we are running pypy-c + class TaskletProxy(object): + """TaskletProxy is needed to give the main_coroutine tasklet behaviour""" + def __init__(self, coro): + self._coro = coro + + def __getattr__(self,attr): + return getattr(self._coro,attr) + + def __str__(self): + return '' % \ + (self.task_id, self.is_alive, self.is_zombie) + + def __reduce__(self): + return getmain, () + + __repr__ = __str__ + + + global main_coroutine + main_coroutine = main_tasklet + main_tasklet = TaskletProxy(main_tasklet) + assert main_tasklet.is_alive and not main_tasklet.is_zombie + tasklet._init(main_tasklet) + squeue = deque() + squeue.append(main_tasklet) +_init() Added: pypy/dist/pypy/lib/stackless_old.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/lib/stackless_old.py Wed Dec 13 18:22:38 2006 @@ -0,0 +1,878 @@ +""" +The Stackless module allows you to do multitasking without using threads. +The essential objects are tasklets and channels. +Please refer to their documentation. +""" + +import traceback +import sys +try: + deadtask = set() +except NameError: + from sets import Set as set + deadtask = set() + + +switches = 0 + +from _stackless import coroutine, greenlet + +__all__ = 'run getcurrent getmain schedule tasklet \ + channel TaskletExit coroutine greenlet'.split() + +main_tasklet = main_coroutine = None +scheduler = None +channel_hook = None +schedlock = False +_schedule_fasthook = None +_schedule_hook = None + +class TaskletExit(Exception):pass + +def SETNEXT(obj, val): + "this function just makes debugging a bit easier :-)" + obj.next = val + +def SETPREV(obj, val): + "just for debugging" + obj.prev = val + +def SETNONE(obj): + "just for debugging" + obj.prev = obj.next = None + +def SWAPVAL(task1, task2): + "just for debugging" + assert task1 is not None + assert task2 is not None + task1.tempval, task2.tempval = task2.tempval, task1.tempval + +def SETVAL(task, val): + "just for debugging" + assert task is not None + task.tempval = val + +last_task_id = 0 + +def restore_exception(etype, value, stack): + """until I find out how to restore an exception on python level""" + #sys.excepthook(etype, value, stack) + raise etype, value, stack + #raise etype(value) + +class TaskletProxy(object): + """TaskletProxy is needed to give the main_coroutine tasklet behaviour""" + def __init__(self, coro): + self.alive = True + self.atomic = False + self.blocked = 0 + self.block_trap = False + self.frame = None + self.ignore_nesting = False + self.is_current = False + self.is_main = False + self.nesting_level = 0 + self.next = self.prev = None + self.paused = False + self.recursion_depth = 0 + self.restorable = False + self.scheduled = False + self.task_id = 0 + self.tempval = None + self._coro = coro + + def __repr__(self): + return tasklet.__str__(self) + + __str__ = __repr__ + + def __getattr__(self,attr): + return getattr(self._coro,attr) + + def __reduce__(self): + return getmain, () + +class bomb(object): + """ + A bomb object is used to hold exceptions in tasklets. + Whenever a tasklet is activated and its tempval is a bomb, + it will explode as an exception. + + You can create a bomb by hand and attach it to a tasklet if you like. + Note that bombs are 'sloppy' about the argument list, which means that + the following works, although you should use '*sys.exc_info()'. + + from stackless import *; import sys + t = tasklet(lambda:42)() + try: 1/0 + except: b = bomb(sys.exc_info()) + + t.tempval = b + nt.run() # let the bomb explode + """ + + traceback = None + type = None + value = None + + def __init__(self,etype=None, value=None, traceback=None): + self.type = etype + self.value = value + self.traceback = traceback + + def _explode(self): + restore_exception(self.type, self.value, self.traceback) + +def make_deadlock_bomb(): + return bomb(RuntimeError, + RuntimeError("Deadlock: the last runnable tasklet cannot be blocked."), + None) + +def curexc_to_bomb(): + return bomb(*sys.exc_info()) + +def enable_softswitch(flag): + """ + enable_softswitch(flag) -- control the switching behavior. + Tasklets can be either switched by moving C stack slices around + or by avoiding stack changes at all. The latter is only possible + in the top interpreter level. Switching it off is for timing and + debugging purposes. This flag exists once for the whole process. + For inquiry only, use the phrase + ret = enable_softswitch(0); enable_softswitch(ret) + By default, soft switching is enabled. + + This is not implemented yet!!!! + """ + pass + +def get_thread_info(task_id): + """ + get_thread_info(task_id) -- return a 3-tuple of the thread's + main tasklet, current tasklet and runcount. + To obtain a list of all thread infos, use + + map (stackless.get_thread_info, stackless.threads) + + This is not implemented yet!!!! + """ + pass + +def set_channel_callback(callable): + """ + set_channel_callback(callable) -- install a callback for channels. + Every send/receive action will call the callback function. + Example: + def channel_cb(channel, tasklet, sending, willblock): + ... + sending and willblock are booleans. + Pass None to switch monitoring off again. + """ + global channel_hook + + channel_hook = callable + +def _schedule_callback(prev, next): + global _schedule_hook + return _schedule_hook(prev, next) + +def set_schedule_callback(func): + """ + set_schedule_callback(callable) -- install a callback for scheduling. + Every explicit or implicit schedule will call the callback function + right before the switch is actually done. + Example: + def schedule_cb(prev, next): + ... + When a tasklet is dying, next is None. + When main starts up or after death, prev is None. + Pass None to switch monitoring off again. + """ + global _schedule_fasthook + global _schedule_hook + global _schedule_callback + + if func is not None and not callable(func): + raise TypeError("schedule callback nust be callable") + _schedule_hook = func + if func is None: + _schedule_fasthook = None + else: + _schedule_fasthook = _schedule_callback + +def run(timeout=0): + """ + run_watchdog(timeout) -- run tasklets until they are all + done, or timeout instructions have passed. Tasklets must + provide cooperative schedule() calls. + If the timeout is met, the function returns. + The calling tasklet is put aside while the tasklets are running. + It is inserted back after the function stops, right before the + tasklet that caused a timeout, if any. + If an exception occours, it will be passed to the main tasklet. + + Please note that the 'timeout' feature is not yet implemented + """ + me = scheduler.current_remove() + if me is not main_tasklet: + raise RuntimeError("run() must be run from the main thread's \ + main tasklet") + return scheduler.schedule_task(me, scheduler._head) + +def getcurrent(): + """ + getcurrent() -- return the currently executing tasklet. + """ + + curr = coroutine.getcurrent() + if curr is main_coroutine: + return main_tasklet + else: + return curr + +def getmain(): + return main_tasklet + +def _do_schedule(retval=None, remove=False): + prev = scheduler._head + next = prev.next + if remove: + scheduler.current_remove() + ret = scheduler.schedule_task(prev, next) + if retval is None: + return ret + else: + return retval + +def schedule_remove(retval=None): + """ + schedule(retval=stackless.current) -- switch to the next runnable tasklet. + The return value for this call is retval, with the current + tasklet as default. + schedule_remove(retval=stackless.current) -- ditto, and remove self. + """ + return _do_schedule(retval, True) + +def schedule(retval=None): + """ + schedule(retval=stackless.current) -- switch to the next runnable tasklet. + The return value for this call is retval, with the current + tasklet as default. + schedule_remove(retval=stackless.current) -- ditto, and remove self. + """ + return _do_schedule(retval, False) + +class tasklet(coroutine): + """ + A tasklet object represents a tiny task in a Python thread. + At program start, there is always one running main tasklet. + New tasklets can be created with methods from the stackless + module. + """ + __slots__ = ['alive','atomic','blocked','block_trap','frame', + 'ignore_nesting','is_current','is_main', + 'nesting_level','next','paused','prev','recursion_depth', + 'restorable','scheduled','tempval','task_id'] + + def __new__(cls, func=None): + return super(tasklet,cls).__new__(cls) + + def __init__(self, func=None): + global last_task_id + super(tasklet,self).__init__() + self.alive = False + self.atomic = False + self.blocked = 0 + self.block_trap = False + self.frame = None + self.ignore_nesting = False + self.is_current = False + self.is_main = False + self.nesting_level = 0 + self.next = self.prev = None + self.paused = False + self.recursion_depth = 0 + self.restorable = False + self.scheduled = False + last_task_id += 1 + self.task_id = last_task_id + self.tempval = None + if func is not None: + self.bind(func) + + def __call__(self, *argl, **argd): + self.setup(*argl, **argd) + return self + + def __repr__(self): + next = None + if self.next is not None: + next = self.next.task_id + prev = None + if self.prev is not None: + prev = self.prev.task_id + if self.blocked: + bs = 'b' + else: + bs = '-' + return 'T%s(%s) (%s, %s)' % (self.task_id, bs, next, prev) + + __str__ = __repr__ + + def bind(self, func): + """ + Binding a tasklet to a callable object. + The callable is usually passed in to the constructor. + In some cases, it makes sense to be able to re-bind a tasklet, + after it has been run, in order to keep its identity. + Note that a tasklet can only be bound when it doesn't have a frame. + """ + if not callable(func): + raise TypeError('tasklet function must be a callable') + SETVAL(self, func) + + def insert(self): + """ + Insert this tasklet at the end of the scheduler list, + given that it isn't blocked. + Blocked tasklets need to be reactivated by channels. + """ + if self.blocked: + raise RuntimeError('You cannot run a blocked tasklet') + if self.is_zombie: + raise RuntimeError('You cannot run an unbound(dead) tasklet') + if self.next is None: + scheduler.current_insert(self) + + def kill(self): + """ + tasklet.kill -- raise a TaskletExit exception for the tasklet. + Note that this is a regular exception that can be caught. + The tasklet is immediately activated. + If the exception passes the toplevel frame of the tasklet, + the tasklet will silently die. + """ + if not self.is_zombie: + coroutine.kill(self) + return self.raise_exception(TaskletExit, TaskletExit()) + + def raise_exception(self, exc, value): + """ + tasklet.raise_exception(exc, value) -- raise an exception for the + tasklet. exc must be a subclass of Exception. + The tasklet is immediately activated. + """ + b = bomb(exc, value) + SETVAL(self, b) + return scheduler.schedule_task(getcurrent(), self) + + def remove(self): + """ + Removing a tasklet from the runnables queue. + Note: If this tasklet has a non-trivial C stack attached, + it will be destructed when the containing thread state is destroyed. + Since this will happen in some unpredictable order, it may cause + unwanted side-effects. Therefore it is recommended to either run + tasklets to the end or to explicitly kill() them. + """ + scheduler.current_remove(self) + + def run(self): + """ + Run this tasklet, given that it isn't blocked. + Blocked tasks need to be reactivated by channels. + """ + scheduler.schedule_task(getcurrent(), self) + + def set_atomic(self, val): + """ + t.set_atomic(flag) -- set tasklet atomic status and return current one. + If set, the tasklet will not be auto-scheduled. + This flag is useful for critical sections which should not be + interrupted. + usage: + tmp = t.set_atomic(1) + # do critical stuff + t.set_atomic(tmp) + Note: Whenever a new tasklet is created, the atomic flag is initialized + with the atomic flag of the current tasklet.Atomic behavior is + additionally influenced by the interpreter nesting level. + See set_ignore_nesting. + """ + tmpval = self.atomic + self.atomic = val + return tmpval + + def set_ignore_nesting(self, flag): + """ + t.set_ignore_nesting(flag) -- set tasklet ignore_nesting status and + return current one. If set, the tasklet may be auto-scheduled, + even if its nesting_level is > 0. + This flag makes sense if you know that nested interpreter levels are + safe for auto-scheduling. This is on your own risk, handle with care! + usage: + tmp = t.set_ignore_nesting(1) + # do critical stuff + t.set_ignore_nesting(tmp) + + Please note that this piece of code does effectively nothing. + """ + tmpval = self.ignore_nesting + self.ignore_nesting = flag + return tmpval + + def finished(self, excinfo): + """called, when coroutine is finished. This gives the tasklet + a chance to clean up after himself.""" + + if self.alive: + self.alive = False + if self.next is not self: + next = self.next + else: + next = getmain() + scheduler.remove_task(self) + deadtask.add(self) + prev = self + if excinfo[0] is not None: + et = excinfo[0] + ev = excinfo[1] + tr = excinfo[2] + b = bomb(et, et(ev), tr) + next = getmain() + SETVAL(next, b) + scheduler.schedule_task(prev, next) + + def setup(self, *argl, **argd): + """ + supply the parameters for the callable + """ + if self.tempval is None: + raise TypeError('cframe function must be callable') + coroutine.bind(self,self.tempval,*argl,**argd) + SETVAL(self, None) + self.alive = True + self.insert() + + def __reduce__(self): + # xxx save more + one, two, three = coroutine.__reduce__(self) + assert one is coroutine + assert two == () + return tasklet, (), (three, self.alive, self.tempval) + + def __setstate__(self, (coro_state, alive, tempval)): + coroutine.__setstate__(self, coro_state) + self.alive = alive + self.tempval = tempval + +def channel_callback(chan, task, sending, willblock): + return channel_hook(chan, task, sending, willblock) + +class channel(object): + """ + A channel object is used for communication between tasklets. + By sending on a channel, a tasklet that is waiting to receive + is resumed. If there is no waiting receiver, the sender is suspended. + By receiving from a channel, a tasklet that is waiting to send + is resumed. If there is no waiting sender, the receiver is suspended. + """ + + def __init__(self): + self.balance = 0 + self.closing = False + self.preference = -1 + self.next = self.prev = self + self.schedule_all = False + self.task_id = -2 + + def __str__(self): + parts = ['%s' % x.task_id for x in self._content()] + return 'channel(' + str(self.balance) + '): ['+' -> '.join(parts)+']' + + def _get_closed(self): + return self.closing and self.next is None + + closed = property(_get_closed) + + def _channel_insert(self, task, d): + self._ins(task) + self.balance += d + task.blocked = d + + def _content(self): + visited = set((self,)) + items = [] + next = self.next + if next is not self: + while next is not None and next not in visited: + items.append(next) + visited.add(next) + next = next.next + return items + + def _queue(self): + if self.next is self: + return None + else: + return self.next + + def _channel_remove(self, d): + ret = self.next + assert isinstance(ret, (tasklet, TaskletProxy)) + self.balance -= d + self._rem(ret) + ret.blocked = 0 + + return ret + + def channel_remove_specific(self, d, task): + # note: we assume that the task is in the channel + self.balance -= d + self._rem(task) + task.blocked = 0 + + return task + + def _ins(self, task): + if (task.next is not None) or (task.prev is not None): + raise AssertionError('task.next and task.prev must be None') + # insert at end + SETPREV(task, self.prev) + SETNEXT(task, self) + SETNEXT(self.prev, task) + SETPREV(self, task) + + def _rem(self, task): + assert task.next is not None + assert task.prev is not None + #remove at end + SETPREV(task.next, task.prev) + SETNEXT(task.prev, task.next) + SETNONE(task) + + def _notify(self, task, d, cando, res): + global schedlock + global channel_hook + if channel_hook is not None: + if schedlock: + raise RuntimeError('Recursive channel call due to callbacks!') + schedlock = 1 + channel_callback(self, task, d > 0, not cando) + schedlock = 0 + + def _channel_action(self, arg, d, stackl): + source = scheduler._head + target = self.next + assert source is getcurrent() + interthread = 0 # no interthreading at the moment + if d > 0: + cando = self.balance < 0 + else: + cando = self.balance > 0 + + assert abs(d) == 1 + SETVAL(source, arg) + if not interthread: + self._notify(source, d, cando, None) + if cando: + # communication 1): there is somebody waiting + target = self._channel_remove(-d) + SWAPVAL(source, target) + if interthread: + raise Exception('no interthreading: I can not be reached...') + else: + if self.schedule_all: + scheduler.current_insert(target) + target = source.next + elif self.preference == -d: + scheduler._set_head(source.next) + scheduler.current_insert(target) + scheduler._set_head(source) + else: + scheduler.current_insert(target) + target = source + else: + # communication 2): there is nobody waiting + if source.block_trap: + raise RuntimeError("this tasklet does not like to be blocked") + if self.closing: + raise StopIteration() + scheduler.current_remove() + self._channel_insert(source, d) + target = scheduler._head + retval = scheduler.schedule_task(source, target) + if interthread: + self._notify(source, d, cando, None) + return retval + + def close(self): + """ + channel.close() -- stops the channel from enlarging its queue. + + If the channel is not empty, the flag 'closing' becomes true. + If the channel is empty, the flag 'closed' becomes true. + """ + self.closing = True + + def next(self): + """ + x.next() -> the next value, or raise StopIteration + """ + if self.closing and not self.balance: + raise StopIteration() + yield self.receive() + + def open(self): + """ + channel.open() -- reopen a channel. See channel.close. + """ + self.closing = False + + def receive(self): + """ + channel.receive() -- receive a value over the channel. + If no other tasklet is already sending on the channel, + the receiver will be blocked. Otherwise, the receiver will + continue immediately, and the sender is put at the end of + the runnables list. + The above policy can be changed by setting channel flags. + """ + return self._channel_action(None, -1, 1) + + def send(self, msg): + """ + channel.send(value) -- send a value over the channel. + If no other tasklet is already receiving on the channel, + the sender will be blocked. Otherwise, the receiver will + be activated immediately, and the sender is put at the end of + the runnables list. + """ + return self._channel_action(msg, 1, 1) + + def send_exception(self, exc, value): + """ + channel.send_exception(exc, value) -- send an exception over the + channel. exc must be a subclass of Exception. + Behavior is like channel.send, but that the receiver gets an exception. + """ + b = bomb(exc, value) + self.send(bomb) + + def send_sequence(self, value): + """ + channel.send_sequence(seq) -- sed a stream of values + over the channel. Combined with a generator, this is + a very efficient way to build fast pipes. + """ + for item in value: + self.send(item) + +class Scheduler(object): + """The singleton Scheduler. Provides mostly scheduling convenience + functions. In normal circumstances, scheduler._head point the + current running tasklet. _head and current_tasklet might be + out of sync just before the actual task switch takes place.""" + + def __init__(self): + self._set_head(getcurrent()) + + def _cleanup(self, task): + task.alive = False + self.remove_task(task) + if self._head is None: + self.current_insert(main_tasklet) + self.schedule_task(getcurrent(), self._head) + + def _set_head(self, task): + self._head = task + + def reset(self): + self.__init__() + + def __len__(self): + return len(self._content()) + + def _content(self): + "convenience method to get the tasklets that are in the queue" + visited = set() + items = [] + next = self._head + if next is not self: + while next is not None and next not in visited: + items.append(next) + visited.add(next) + next = next.next + return items + + def __str__(self): + parts = ['%s' % x.task_id for x in self._content()] + if self._head is not self: + currid = self._head.task_id + else: + currid = -1 + return 'Scheduler: [' + ' -> '.join(parts) + ']' + + def _chain_insert(self, task): + assert task.next is None + assert task.prev is None + if self._head is None: + SETNEXT(task, task) + SETPREV(task, task) + self._set_head(task) + else: + r = self._head + l = r.prev + SETNEXT(l, task) + SETPREV(r, task) + SETPREV(task, l) + SETNEXT(task, r) + + def remove_task(self, task): + l = task.prev + r = task.next + SETNEXT(l, r) + SETPREV(r, l) + self._set_head(r) + if r == task: + self._set_head(None) + SETNONE(task) + + return task + + def _chain_remove(self): + if self._head is None: + return None + return self.remove_task(self._head) + + def current_insert(self, task): + "insert 'task' at end of running queue" + self._chain_insert(task) + + def current_insert_after(self, task): + "insert 'task' just after the current one" + if self._head is not None: + curr = self._head + self._set_head(curr.next) + self._chain_insert(task) + self._set_head(curr) + else: + self.current_insert(task) + + def current_remove(self): + "remove current tasklet from queue" + return self._chain_remove() + + def channel_remove_slow(self, task): + prev = task.prev + while not isinstance(prev, channel): + prev = prev.prev + chan = prev + assert chan.balance + if chan.balance > 0: + d = 1 + else: + d = -1 + return chan.channel_remove_specific(d, task) + + def bomb_explode(self, task): + thisbomb = task.tempval + assert isinstance(thisbomb, bomb) + SETVAL(task, None) + thisbomb._explode() +# try: +# thisbomb._explode() +# finally: +# if getcurrent() == main_tasklet: +# sys.excepthook(thisbomb.type, +# thisbomb.value, +# thisbomb.traceback) +# sys.exit() + + def _notify_schedule(self, prev, next, errflag): + if _schedule_fasthook is not None: + global schedlock + if schedlock: + raise RuntimeError('Recursive scheduler call due to callbacks!') + schedlock = True + ret = _schedule_fasthook(prev, next) + schedlock = False + if ret: + return errflag + + def schedule_task_block(self, prev): + if main_tasklet.next is None: + if isinstance(prev.tempval, bomb): + SETVAL(main_tasklet, prev.tempval) + return self.schedule_task(prev, main_tasklet) + retval = make_deadlock_bomb() + SETVAL(prev, retval) + + return self.schedule_task(prev, prev) + + def schedule_task(self, prev, next): + global switches + switches += 1 + myswitch = switches + if next is None: + return self.schedule_task_block(prev) + if next.blocked: + self.channel_remove_slow(next) + self.current_insert(next) + elif next.next is None: + self.current_insert(next) + if prev is next: + retval = prev.tempval + if isinstance(retval, bomb): + self.bomb_explode(prev) + return retval + self._notify_schedule(prev, next, None) + self._set_head(next) + + try: + res = next.switch() + except: + pass + + for dead in tuple(deadtask): + deadtask.discard(dead) + + # the code below should work, but doesn't + + #if not dead.is_zombie: + # coroutine.kill(dead) + # del dead + + retval = prev.tempval + if isinstance(retval, bomb): + self.bomb_explode(prev) + + return retval + + def schedule_callback(self, prev, next): + ret = _schedule_hook(prev, next) + if ret: + return 0 + else: + return -1 + + def __reduce__(self): + if self is scheduler: + return _return_sched, (), () + +def _return_sched(): + return scheduler + +def __init(): + global main_tasklet + global main_coroutine + global scheduler + main_coroutine = c = coroutine.getcurrent() + main_tasklet = TaskletProxy(c) + SETNEXT(main_tasklet, main_tasklet) + SETPREV(main_tasklet, main_tasklet) + main_tasklet.is_main = True + scheduler = Scheduler() + +__init() + Modified: pypy/dist/pypy/module/_stackless/test/test_stackless.py ============================================================================== --- pypy/dist/pypy/module/_stackless/test/test_stackless.py (original) +++ pypy/dist/pypy/module/_stackless/test/test_stackless.py Wed Dec 13 18:22:38 2006 @@ -25,6 +25,7 @@ def test_simple(self): import stackless + stackless._init() rlist = [] @@ -49,6 +50,7 @@ def test_with_channel(self): import stackless + stackless._init() rlist = [] def f(outchan): @@ -79,6 +81,7 @@ def test_counter(self): import random import stackless + stackless._init() numbers = range(20) random.shuffle(numbers) @@ -103,6 +106,7 @@ def test_scheduling_cleanup(self): import stackless + stackless._init() rlist = [] def f(): rlist.append('fb') @@ -131,6 +135,7 @@ def test_except(self): import stackless + stackless._init() rlist = [] def f(): @@ -163,6 +168,7 @@ def test_except_full(self): import stackless + stackless._init() rlist = [] def f(): @@ -193,8 +199,9 @@ assert rlist == "bg f E bh ag ah".split() def test_kill(self): - skip('kill is not really working') import stackless + stackless._init() + def f():pass t = stackless.tasklet(f)() t.kill() @@ -208,6 +215,7 @@ output.append(args) import stackless + stackless._init() def aCallable(value): print_("aCallable:", value) @@ -235,10 +243,12 @@ def test_simple_channel(self): output = [] + #skip('') def print_(*args): output.append(args) import stackless + stackless._init() def Sending(channel): print_("sending") @@ -251,9 +261,15 @@ ch=stackless.channel() task=stackless.tasklet(Sending)(ch) - stackless.schedule(task) + + # Note: the argument, schedule is taking is the value, + # schedule returns, not the task that runs next + + #stackless.schedule(task) + stackless.schedule() task2=stackless.tasklet(Receiving)(ch) - stackless.schedule(task2) + #stackless.schedule(task2) + stackless.schedule() stackless.run() @@ -261,12 +277,14 @@ def test_balance_zero(self): import stackless + stackless._init() ch=stackless.channel() assert ch.balance == 0 def test_balance_send(self): import stackless + stackless._init() def Sending(channel): channel.send("foo") @@ -274,13 +292,13 @@ ch=stackless.channel() task=stackless.tasklet(Sending)(ch) - stackless.schedule(task) stackless.run() assert ch.balance == 1 def test_balance_recv(self): import stackless + stackless._init() def Receiving(channel): channel.receive() @@ -288,7 +306,6 @@ ch=stackless.channel() task=stackless.tasklet(Receiving)(ch) - stackless.schedule(task) stackless.run() assert ch.balance == -1 @@ -299,6 +316,7 @@ output.append(args) import stackless + stackless._init() def f(i): print_(i) @@ -314,6 +332,7 @@ output.append(args) import stackless + stackless._init() def f(i): print_(i) @@ -330,6 +349,7 @@ output.append(args) import stackless + stackless._init() def Loop(i): for x in range(3): @@ -344,55 +364,3 @@ ('schedule', 1), ('schedule', 2), ('schedule', 1), ('schedule', 2),] -class AppTest_StacklessPickling: - - def setup_class(cls): - if not option.runappdirect: - skip('pure appdirect test (run with -A)') - cls.space = gettestobjspace(usemodules=('_stackless',)) - - def test_basic_tasklet_pickling(self): - import stackless - from stackless import run, schedule, tasklet - import pickle - - output = [] - - import new - - mod = new.module('mod') - mod.output = output - - exec """from stackless import schedule - -def aCallable(name): - output.append(('b', name)) - schedule() - output.append(('a', name)) -""" in mod.__dict__ - import sys - sys.modules['mod'] = mod - aCallable = mod.aCallable - - - tasks = [] - for name in "ABCDE": - tasks.append(tasklet(aCallable)(name)) - - schedule() - - assert output == [('b', x) for x in "ABCDE"] - del output[:] - pickledTasks = pickle.dumps(tasks) - - schedule() - assert output == [('a', x) for x in "ABCDE"] - del output[:] - - unpickledTasks = pickle.loads(pickledTasks) - for task in unpickledTasks: - task.insert() - - schedule() - assert output == [('a', x) for x in "ABCDE"] - Added: pypy/dist/pypy/module/_stackless/test/test_stackless_pickling.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/module/_stackless/test/test_stackless_pickling.py Wed Dec 13 18:22:38 2006 @@ -0,0 +1,55 @@ +from pypy.conftest import gettestobjspace, option +from py.test import skip + +class AppTest_StacklessPickling: + + def setup_class(cls): + if not option.runappdirect: + skip('pure appdirect test (run with -A)') + cls.space = gettestobjspace(usemodules=('_stackless',)) + + def test_basic_tasklet_pickling(self): + import stackless + from stackless import run, schedule, tasklet + import pickle + + output = [] + + import new + + mod = new.module('mod') + mod.output = output + + exec """from stackless import schedule + +def aCallable(name): + output.append(('b', name)) + schedule() + output.append(('a', name)) +""" in mod.__dict__ + import sys + sys.modules['mod'] = mod + aCallable = mod.aCallable + + + tasks = [] + for name in "ABCDE": + tasks.append(tasklet(aCallable)(name)) + + schedule() + + assert output == [('b', x) for x in "ABCDE"] + del output[:] + pickledTasks = pickle.dumps(tasks) + + schedule() + assert output == [('a', x) for x in "ABCDE"] + del output[:] + + unpickledTasks = pickle.loads(pickledTasks) + for task in unpickledTasks: + task.insert() + + schedule() + assert output == [('a', x) for x in "ABCDE"] + From pedronis at codespeak.net Wed Dec 13 18:37:12 2006 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Wed, 13 Dec 2006 18:37:12 +0100 (CET) Subject: [pypy-svn] r35690 - in pypy/dist/pypy/rpython: . lltypesystem test Message-ID: <20061213173712.B858310084@code0.codespeak.net> Author: pedronis Date: Wed Dec 13 18:37:08 2006 New Revision: 35690 Modified: pypy/dist/pypy/rpython/llinterp.py pypy/dist/pypy/rpython/lltypesystem/lloperation.py pypy/dist/pypy/rpython/test/test_rint.py Log: finish llong_neg/abs_ovf support Modified: pypy/dist/pypy/rpython/llinterp.py ============================================================================== --- pypy/dist/pypy/rpython/llinterp.py (original) +++ pypy/dist/pypy/rpython/llinterp.py Wed Dec 13 18:37:08 2006 @@ -769,6 +769,20 @@ except OverflowError: self.make_llexception() + def op_llong_neg_ovf(self, x): + assert type(x) is r_longlong + try: + return ovfcheck(-x) + except OverflowError: + self.make_llexception() + + def op_llong_abs_ovf(self, x): + assert type(x) is r_longlong + try: + return ovfcheck(abs(x)) + except OverflowError: + self.make_llexception() + def _makefunc2(fn, operator, xtype, ytype=None): import sys d = sys._getframe(1).f_locals Modified: pypy/dist/pypy/rpython/lltypesystem/lloperation.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/lloperation.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/lloperation.py Wed Dec 13 18:37:08 2006 @@ -223,7 +223,9 @@ 'llong_is_true': LLOp(canfold=True), 'llong_neg': LLOp(canfold=True), + 'llong_neg_ovf': LLOp(canraise=(OverflowError,)), 'llong_abs': LLOp(canfold=True), + 'llong_abs_ovf': LLOp(canraise=(OverflowError,)), 'llong_invert': LLOp(canfold=True), 'llong_add': LLOp(canfold=True), Modified: pypy/dist/pypy/rpython/test/test_rint.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_rint.py (original) +++ pypy/dist/pypy/rpython/test/test_rint.py Wed Dec 13 18:37:08 2006 @@ -1,8 +1,9 @@ -import sys +import sys, operator from pypy.translator.translator import TranslationContext from pypy.annotation import model as annmodel from pypy.rpython.test import snippet -from pypy.rlib.rarithmetic import r_uint, r_longlong, r_ulonglong +from pypy.rlib.rarithmetic import r_int, r_uint, r_longlong, r_ulonglong +from pypy.rlib.rarithmetic import ovfcheck from pypy.rpython.test.tool import BaseRtypingTest, LLRtypeMixin, OORtypeMixin class TestSnippet(object): @@ -174,6 +175,24 @@ assert res == f(inttype(0)) assert type(res) == inttype + def test_neg_abs_ovf(self): + for op in (operator.neg, abs): + def f(x): + try: + return ovfcheck(op(x)) + except OverflowError: + return 0 + res = self.interpret(f, [-1]) + assert res == 1 + res = self.interpret(f, [int(-1<<(r_int.BITS-1))]) + assert res == 0 + + res = self.interpret(f, [r_longlong(-1)]) + assert res == 1 + res = self.interpret(f, [r_longlong(-1)<<(r_longlong.BITS-1)]) + assert res == 0 + + class TestLLtype(BaseTestRint, LLRtypeMixin): pass From afayolle at codespeak.net Wed Dec 13 18:55:03 2006 From: afayolle at codespeak.net (afayolle at codespeak.net) Date: Wed, 13 Dec 2006 18:55:03 +0100 (CET) Subject: [pypy-svn] r35691 - pypy/dist/pypy/translator/goal Message-ID: <20061213175503.07DCD10092@code0.codespeak.net> Author: afayolle Date: Wed Dec 13 18:55:02 2006 New Revision: 35691 Modified: pypy/dist/pypy/translator/goal/translate.py Log: call target.get_additional_config options before target.handle_config, so that the options can be created before they are set Modified: pypy/dist/pypy/translator/goal/translate.py ============================================================================== --- pypy/dist/pypy/translator/goal/translate.py (original) +++ pypy/dist/pypy/translator/goal/translate.py Wed Dec 13 18:55:02 2006 @@ -145,10 +145,6 @@ if args and not targetspec_dic.get('take_options', False): log.WARNING("target specific arguments supplied but will be ignored: %s" % ' '.join(args)) - # let the target modify or prepare itself - # based on the config - if 'handle_config' in targetspec_dic: - targetspec_dic['handle_config'](config) # give the target the possibility to get its own configuration options # into the config if 'get_additional_config_options' in targetspec_dic: @@ -158,6 +154,11 @@ existing_config=config, translating=True) + # let the target modify or prepare itself + # based on the config + if 'handle_config' in targetspec_dic: + targetspec_dic['handle_config'](config) + if 'handle_translate_config' in targetspec_dic: targetspec_dic['handle_translate_config'](translateconfig) From arigo at codespeak.net Wed Dec 13 19:35:42 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 13 Dec 2006 19:35:42 +0100 (CET) Subject: [pypy-svn] r35692 - pypy/dist/pypy/doc Message-ID: <20061213183542.81E3D1009F@code0.codespeak.net> Author: arigo Date: Wed Dec 13 19:35:39 2006 New Revision: 35692 Modified: pypy/dist/pypy/doc/draft-jit-outline.txt Log: BTA and hints. Modified: pypy/dist/pypy/doc/draft-jit-outline.txt ============================================================================== --- pypy/dist/pypy/doc/draft-jit-outline.txt (original) +++ pypy/dist/pypy/doc/draft-jit-outline.txt Wed Dec 13 19:35:39 2006 @@ -146,7 +146,98 @@ Binding-time analysis ========================================= -Hint annotator and hint(concrete=True)... +PyPy performs binding-time analysis of the source RPython_ program after +it has been turned to `low-level graphs`_, i.e. at the level at which +operations manipulate `pointer-and-structures-like objects`_. + +The binding-time analyzer of our translation toolchain is based on the +same type inference engine that is used on the source RPython program, +the annotator_. In this mode, it is called the *hint-annotator*; it +operates over input graphs that are already low-level instead of +RPython-level, and propagates annotations that do not track types but +value dependencies and manually-provided binding time hints. + +Hints +---------------------------------- + +Our goal in designing our approach to binding-time analysis was to +minimize the number of explicit hints that the user must provide in the +source of the RPython program. This minimalism was not pushed to +extremes, though, to keep the hint-annotator reasonably simple. + +The driving idea was that hints should be need-oriented. In a program +like an interpreter, there are a few clear places where it would be +beneficial for a given value to be known at compile-time, i.e. green. +This is where we require the hints to be added. + +The normal process of the hint-annotator is to propagate the binding +time (i.e. color) of the variables using the following kind of rules: + +* For a foldable operation (i.e. one without side effect and which + depends only on its argument's value), if all arguments are green, + then the result can be green too. + +* Non-foldable operations always produce a red result. + +* At join points, where multiple possible values (depending on control + flow) are meeting into a fresh variable, if any incoming value comes + from a red variable, the result is red. Otherwise, the color of the + result might be green. We do not make it eagerly green, because of + the control flow dependency: the residual function is basically a + constant-folded copy of the source function, so it might retain some + of the same control flow. The value that needs to be stored in the + fresh join variable thus depends on which branches are taken in the + residual graph. + +The hint-annotator assumes that all variables are red by default (with +the exception of constants, which are always green). It then propagates +annotations that record dependency information. When encountering the +user-provided hints, the dependency information is used to make some +variables green. (Technically, the color itself is not part of the +annotations propagated by the annotator.) All hints are in the form of +an operation ``hint(v1, someflag=True)`` which semantically just returns +its first argument unmodified. The three kinds of hints that are useful +in practice are: + +``v2 = hint(v1, concrete=True)`` + This is interpreted by the hint-annotator as a request for both + ``v1`` and ``v2`` to be green. It is used in places where the + programmer considers the knowledge of the value to be essential. + This hint has a *global* effect on the binding times: it means that + not only ``v1`` but all the values that ``v1`` depends on - + recursively - are forced to be green. Typically, it can only be + applied on values that directly depend on some input arguments, + making these input arguments green. The hint-annotator complains if + the dependencies of ``v1`` include a value that cannot be green, + like a value read out of a field out of a non-immutable structure. + + The color of the result ``v2`` is green as well. Unlike ``v1``, all + further operations involving ``v2`` are checked to not meet any red + variable (i.e. ``v2`` is eagerly and recursively propagated, while + ``v1`` is only green and may be involved in further operations that + will produce red results). + +``v2 = hint(v1, promote=True)`` + This hint is a *local* request for ``v2`` to be green. Unlike the + previous hint, this one has no effect on the color of ``v1`` (which + is typically red - the hint has no effect otherwise). + + Note that in classical approaches to partial evalution, it is not + possible to copy a red value into a green one. The implementation + of such an operation ("promotion") is only possible in a + "just-in-time" approach that only Psyco_ implemented so far (to the + best of our knowledge). Our hint is a direct generalization of the + latter. + +``v2 = hint(v1, variable=True)`` + Force ``v2`` to be red, even if ``v1`` is green. + +A program using promotion also need to contain a "global merge point" +hint; this has no effect on the hint-annotator and is described in the +section about promotion_. + + + calls... @@ -189,10 +280,12 @@ ... +.. _promotion: + Promotion and global merges ----------------------------- -... +...global merge point... Partial data ------------- From pedronis at codespeak.net Wed Dec 13 19:38:32 2006 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Wed, 13 Dec 2006 19:38:32 +0100 (CET) Subject: [pypy-svn] r35693 - pypy/dist/pypy/rlib Message-ID: <20061213183832.F1E81100A4@code0.codespeak.net> Author: pedronis Date: Wed Dec 13 19:38:26 2006 New Revision: 35693 Modified: pypy/dist/pypy/rlib/rarithmetic.py Log: forgot to check this in :( Modified: pypy/dist/pypy/rlib/rarithmetic.py ============================================================================== --- pypy/dist/pypy/rlib/rarithmetic.py (original) +++ pypy/dist/pypy/rlib/rarithmetic.py Wed Dec 13 19:38:26 2006 @@ -66,7 +66,7 @@ # to be used as ovfcheck(x y) # raise OverflowError if the operation did overflow assert not isinstance(r, r_uint), "unexpected ovf check on unsigned" - if isinstance(r, long): + if type(r) is long: raise OverflowError, "signed integer expression did overflow" return r From pedronis at codespeak.net Wed Dec 13 19:59:27 2006 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Wed, 13 Dec 2006 19:59:27 +0100 (CET) Subject: [pypy-svn] r35694 - pypy/dist/pypy/doc Message-ID: <20061213185927.E5D0910061@code0.codespeak.net> Author: pedronis Date: Wed Dec 13 19:59:22 2006 New Revision: 35694 Modified: pypy/dist/pypy/doc/draft-jit-outline.txt Log: typos, small fixes, fix references. Modified: pypy/dist/pypy/doc/draft-jit-outline.txt ============================================================================== --- pypy/dist/pypy/doc/draft-jit-outline.txt (original) +++ pypy/dist/pypy/doc/draft-jit-outline.txt Wed Dec 13 19:59:22 2006 @@ -150,7 +150,7 @@ it has been turned to `low-level graphs`_, i.e. at the level at which operations manipulate `pointer-and-structures-like objects`_. -The binding-time analyzer of our translation toolchain is based on the +The binding-time analyzer of our translation tool-chain is based on the same type inference engine that is used on the source RPython program, the annotator_. In this mode, it is called the *hint-annotator*; it operates over input graphs that are already low-level instead of @@ -174,7 +174,7 @@ time (i.e. color) of the variables using the following kind of rules: * For a foldable operation (i.e. one without side effect and which - depends only on its argument's value), if all arguments are green, + depends only on its argument values), if all arguments are green, then the result can be green too. * Non-foldable operations always produce a red result. @@ -211,18 +211,18 @@ the dependencies of ``v1`` include a value that cannot be green, like a value read out of a field out of a non-immutable structure. - The color of the result ``v2`` is green as well. Unlike ``v1``, all - further operations involving ``v2`` are checked to not meet any red - variable (i.e. ``v2`` is eagerly and recursively propagated, while - ``v1`` is only green and may be involved in further operations that - will produce red results). + The color of the result ``v2`` is green as well. Unlike ``v1``, + all further operations involving ``v2`` are checked to not meet + any red variable (i.e. ``v2`` color is eagerly and recursively + propagated, while ``v1`` is only green and may be involved in + further operations that will produce red results). ``v2 = hint(v1, promote=True)`` This hint is a *local* request for ``v2`` to be green. Unlike the previous hint, this one has no effect on the color of ``v1`` (which is typically red - the hint has no effect otherwise). - Note that in classical approaches to partial evalution, it is not + Note that in classical approaches to partial evaluation, it is not possible to copy a red value into a green one. The implementation of such an operation ("promotion") is only possible in a "just-in-time" approach that only Psyco_ implemented so far (to the @@ -313,3 +313,9 @@ ... + +.. _`RPython`: coding-guide.html#rpython +.. _`low-level graphs`: rtyper.html +.. _`pointer-and-structures-like objects`: rtyper.html#low-level-types +.. _`annotator`: dynamic-language-translation.html +.. _Psyco: http://psyco.sourceforge.net From arigo at codespeak.net Wed Dec 13 20:20:14 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 13 Dec 2006 20:20:14 +0100 (CET) Subject: [pypy-svn] r35695 - pypy/dist/pypy/doc Message-ID: <20061213192014.92C0310075@code0.codespeak.net> Author: arigo Date: Wed Dec 13 20:20:12 2006 New Revision: 35695 Modified: pypy/dist/pypy/doc/draft-jit-outline.txt Log: Calls in the hint-annotator. Modified: pypy/dist/pypy/doc/draft-jit-outline.txt ============================================================================== --- pypy/dist/pypy/doc/draft-jit-outline.txt (original) +++ pypy/dist/pypy/doc/draft-jit-outline.txt Wed Dec 13 20:20:12 2006 @@ -232,20 +232,62 @@ ``v2 = hint(v1, variable=True)`` Force ``v2`` to be red, even if ``v1`` is green. -A program using promotion also need to contain a "global merge point" +A program using promotion also needs to contain a ``global_merge_point`` hint; this has no effect on the hint-annotator and is described in the section about promotion_. +Calls +---------------------------------- +The ``concrete`` hint requires precise tracking of dependencies across +calls. More specifically, unlike the regular type-inferencing +annotator, the hint-annotator does not simply propagate this information +through called function, but keep all dependency information local to a +function. The problem is best shown by an example:: + + x = ... + y = ... + z = f(x, y) + +In this example, assuming that ``f(x, y)`` has no side effects, then we +want the dependency set of ``z`` to be the union of the dependencies of +``x`` and ``y`` (if both contribute to the result). But if another call +site calls ``f(x2, y2)`` then precision would be lost - the annotations +that would propagate within ``f`` would be marked as depending on all of +``x``, ``x2``, ``y`` and ``y2``, and then so would ``z``. + +To fix this problem, we only propagate dependencies that are local to a +function. Around a call like ``z = f(x, y)``, we check in the +annotations of the function ``f`` on which input arguments the result is +marked as depending on, and we reproduce the same dependency +relationship locally between ``x`` and ``y`` and ``z``. + +There are other aspects of the information carried by annotations that +are used in the "usual" annotator way, i.e. directly propagated between +caller and callee and back. If the result ``z`` of a call is forced to +be green by a ``concrete`` hint, then this forcing effect is propagated +inside the callee (more precisely, in a fresh copy of the callee, so +that forced and non-forced call sites can respecitvely call a +mostly-green and a mostly-red version of the function; this is done with +the technique of `specialization of functions`_ that is already +available in the normal annotator). + +Also, if all call sites provide a green value for an argument, then the +callee's corresponding input argument can safely be green. (This can +only be determined at the end of the process, though, after all call +sites are known and stable enough; we use another fixpoint loop for +this.) +Deep freezing +---------------------------------- -calls... +deepfreeze... -green propagation at fixpoint... +Blue containers +---------------------------------- -deepfreeze... +Undocumented yet. Not implemented in the timeshifter, so not used so far. -blue containers... .. _timeshifting: From pedronis at codespeak.net Wed Dec 13 20:32:17 2006 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Wed, 13 Dec 2006 20:32:17 +0100 (CET) Subject: [pypy-svn] r35696 - pypy/dist/pypy/translator/tool Message-ID: <20061213193217.268A1100A3@code0.codespeak.net> Author: pedronis Date: Wed Dec 13 20:32:12 2006 New Revision: 35696 Modified: pypy/dist/pypy/translator/tool/pdbplus.py Log: a different prompt for pdbplus Modified: pypy/dist/pypy/translator/tool/pdbplus.py ============================================================================== --- pypy/dist/pypy/translator/tool/pdbplus.py (original) +++ pypy/dist/pypy/translator/tool/pdbplus.py Wed Dec 13 20:32:12 2006 @@ -15,6 +15,7 @@ def __init__(self, translator): pdb.Pdb.__init__(self) + self.prompt = "(Pdb+)" self.translator = translator self.exposed = {} From pedronis at codespeak.net Wed Dec 13 20:40:30 2006 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Wed, 13 Dec 2006 20:40:30 +0100 (CET) Subject: [pypy-svn] r35697 - pypy/dist/pypy/doc Message-ID: <20061213194030.B65C31008A@code0.codespeak.net> Author: pedronis Date: Wed Dec 13 20:40:26 2006 New Revision: 35697 Modified: pypy/dist/pypy/doc/draft-jit-outline.txt Log: fix reference, small fixes. Modified: pypy/dist/pypy/doc/draft-jit-outline.txt ============================================================================== --- pypy/dist/pypy/doc/draft-jit-outline.txt (original) +++ pypy/dist/pypy/doc/draft-jit-outline.txt Wed Dec 13 20:40:26 2006 @@ -242,7 +242,7 @@ The ``concrete`` hint requires precise tracking of dependencies across calls. More specifically, unlike the regular type-inferencing annotator, the hint-annotator does not simply propagate this information -through called function, but keep all dependency information local to a +through called functions, but keeps all dependency information local to a function. The problem is best shown by an example:: x = ... @@ -267,7 +267,7 @@ caller and callee and back. If the result ``z`` of a call is forced to be green by a ``concrete`` hint, then this forcing effect is propagated inside the callee (more precisely, in a fresh copy of the callee, so -that forced and non-forced call sites can respecitvely call a +that forced and non-forced call sites can respectively call a mostly-green and a mostly-red version of the function; this is done with the technique of `specialization of functions`_ that is already available in the normal annotator). @@ -360,4 +360,5 @@ .. _`low-level graphs`: rtyper.html .. _`pointer-and-structures-like objects`: rtyper.html#low-level-types .. _`annotator`: dynamic-language-translation.html +.. _`specialization of functions`: dynamic-language-translation.html#specialization .. _Psyco: http://psyco.sourceforge.net From pedronis at codespeak.net Wed Dec 13 20:48:36 2006 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Wed, 13 Dec 2006 20:48:36 +0100 (CET) Subject: [pypy-svn] r35698 - pypy/dist/pypy/doc Message-ID: <20061213194836.43FD6100A4@code0.codespeak.net> Author: pedronis Date: Wed Dec 13 20:48:33 2006 New Revision: 35698 Modified: pypy/dist/pypy/doc/draft-jit-outline.txt Log: fix one ref XXX, more XXX, uniform style for them. Modified: pypy/dist/pypy/doc/draft-jit-outline.txt ============================================================================== --- pypy/dist/pypy/doc/draft-jit-outline.txt (original) +++ pypy/dist/pypy/doc/draft-jit-outline.txt Wed Dec 13 20:48:33 2006 @@ -14,8 +14,7 @@ transparently introduced by and during the translation process. Partial evaluation techniques should, at least theoretically, allow -such a derivation of a compiler from an interpreter. XXX scalability -issues references ... +such a derivation of a compiler from an interpreter. (XXX references) The forest of flow graphs that the translation process generates and transforms constitutes a reasonable base for the necessary analyses. @@ -32,6 +31,7 @@ Generating extensions can be produced by self-applying partial evaluators, but this approach may lead to not optimal results or be not scalable +(XXX expand this argument) For PyPy, our approach aims at producing the generating extension more directly from the analysed interpreter in the form of a forest of flow @@ -44,8 +44,9 @@ Currently we base the binding time computation on propagating the information based on a few hint inserted in the interpreter. Propagation -is implemented by reusing our annotation/type inference framework XXX -ref. +is implemented by reusing our `annotation/type inference framework`__. + +__ annotator_ The code produced by a generating extension for an input program may not be good, especially for a dynamic language, because essentially @@ -68,7 +69,7 @@ value. Concretely the promotion expands into a switch to choose based on the run-time value one of the possible specialised code paths, plus a default case to compile further specialised paths. This can be also -thought as a generalisation of polymorphic inline caches XXX ref. +thought as a generalisation of polymorphic inline caches (XXX reference). Terminology From arigo at codespeak.net Wed Dec 13 21:02:40 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 13 Dec 2006 21:02:40 +0100 (CET) Subject: [pypy-svn] r35699 - pypy/dist/pypy/doc Message-ID: <20061213200240.3622310098@code0.codespeak.net> Author: arigo Date: Wed Dec 13 21:02:38 2006 New Revision: 35699 Modified: pypy/dist/pypy/doc/draft-jit-outline.txt Log: Deep freezing in the hint-annotator. Modified: pypy/dist/pypy/doc/draft-jit-outline.txt ============================================================================== --- pypy/dist/pypy/doc/draft-jit-outline.txt (original) +++ pypy/dist/pypy/doc/draft-jit-outline.txt Wed Dec 13 21:02:38 2006 @@ -237,6 +237,15 @@ hint; this has no effect on the hint-annotator and is described in the section about promotion_. + +.. _`example above`: + +Example +---------------------------------- + +XXX + + Calls ---------------------------------- @@ -279,10 +288,39 @@ sites are known and stable enough; we use another fixpoint loop for this.) + Deep freezing ---------------------------------- -deepfreeze... +Among the low-level operations, the one that reads data from a structure +in memory (``getfield``) requires special care. In a first +approximation it can only return a red value, because the reading from +the structure cannot be performed at compile-time - the structure may be +mutated between compile-time and the point at run-time where the read +was supposed to occur in the original code. + +This is a problem in most real-life examples. Unlike our `example +above`_, input arguments to such functions are typically not just +strings and integers but complex data structures. To produce sensible +results, it is necessary to assume that some of these data structures +will not be mutated after the compile-time process used their content. +For example, PyPy's own interpreter works with an instance of a PyCode +class containing not only a string representing the bytecode, but +various simple Python objects (tuple of names, ...). None of this data +can be modified after its construction, though. + +To express this, we use a hint ``v2 = hint(v1, deepfreeze=True)``, where +``v1`` is a pointer (in the low-level graph - it typically comes from a +regular RPython object reference in the RPython source). The +hint-annotation will then propagate a "deepfrozen" flag on the +annotation attached to ``v2``. If ``v2`` is green, a ``getfield(v2, +"name")`` operation then also returns a green. Moreover, the result of +the ``getfield`` is also itself "deepfrozen". We decided to implement +recursive freezing and not one-level-only freezing, as the latter seems +more fragile with respect to changes both in the RPython source and in +the way the source maps to low-level graphs; but variants could easily +be implemented if needed. + Blue containers ---------------------------------- @@ -298,6 +336,15 @@ intro and basics +Basics +-------- + +...red vs green operations... + +XXX Note that the "deepfrozen" flag is used at compile-time on red +values too, to influence the details of how residual ``getfield`` +operations should be generated. + Transform vs hrtyping ----------------------- From pedronis at codespeak.net Wed Dec 13 21:23:54 2006 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Wed, 13 Dec 2006 21:23:54 +0100 (CET) Subject: [pypy-svn] r35700 - pypy/dist/pypy/doc Message-ID: <20061213202354.8AB2B10086@code0.codespeak.net> Author: pedronis Date: Wed Dec 13 21:23:52 2006 New Revision: 35700 Modified: pypy/dist/pypy/doc/draft-jit-outline.txt Log: small example with some commenting Modified: pypy/dist/pypy/doc/draft-jit-outline.txt ============================================================================== --- pypy/dist/pypy/doc/draft-jit-outline.txt (original) +++ pypy/dist/pypy/doc/draft-jit-outline.txt Wed Dec 13 21:23:52 2006 @@ -243,8 +243,37 @@ Example ---------------------------------- -XXX +Let's consider a very small interpreter-like example:: + def ll_plus_minus(s, x, y): + acc = x + pc = 0 + while pc < len(s): + op = s[pc] + op = hint(op, concrete=True) + if op == '+': + acc += y + elif op == '-': + acc -= y + pc += 1 + return acc + +``s`` here is an input program, simply a string of "+" or "-", x and y +are integer input arguments. + +The annotation of ``op = hint(op, concrete=True)`` will follow the +dependencies of the argument ``op``, which is the result of ``op = +s[pc]``, so both ``s``and ``pc`` will be marked green. ``x``, ``y`` +and ``acc`` will stay red. + +The result ``op`` compared to the possible "instructions" will also be +green. Because ``s``is green also ``len(s)`` will be. + +Using this information the *timeshifting* of the ``ll_plus_minus``, +should be able to produce code that unfolds the loop and respectively +folds instruction dispatching (the ifs) at compile-time, because the +while condition, the ``pc``increment, and the dispatching are +operations among only greens (constants are green by default). Calls ---------------------------------- From fijal at codespeak.net Wed Dec 13 21:27:49 2006 From: fijal at codespeak.net (fijal at codespeak.net) Date: Wed, 13 Dec 2006 21:27:49 +0100 (CET) Subject: [pypy-svn] r35701 - pypy/dist/pypy/translator/js/test Message-ID: <20061213202749.E67121009B@code0.codespeak.net> Author: fijal Date: Wed Dec 13 21:27:43 2006 New Revision: 35701 Modified: pypy/dist/pypy/translator/js/test/test_rpython.py Log: Skip those tests, they are broken anyway Modified: pypy/dist/pypy/translator/js/test/test_rpython.py ============================================================================== --- pypy/dist/pypy/translator/js/test/test_rpython.py (original) +++ pypy/dist/pypy/translator/js/test/test_rpython.py Wed Dec 13 21:27:43 2006 @@ -7,7 +7,7 @@ from pypy.rpython.test.test_rtuple import BaseTestRtuple from pypy.rpython.test.test_rstr import BaseTestRstr -#py.test.skip("Test in progress") +py.test.skip("Those tests are totally broken, need deeper look") class TestJsException(JsTest, BaseTestException): pass From fijal at codespeak.net Wed Dec 13 21:30:54 2006 From: fijal at codespeak.net (fijal at codespeak.net) Date: Wed, 13 Dec 2006 21:30:54 +0100 (CET) Subject: [pypy-svn] r35702 - pypy/dist/pypy/translator/js/test Message-ID: <20061213203054.68BC61009F@code0.codespeak.net> Author: fijal Date: Wed Dec 13 21:30:52 2006 New Revision: 35702 Modified: pypy/dist/pypy/translator/js/test/runtest.py Log: This way it's closer to what I want to achieve, but breaks tests. It seems that they were never working, so I've disabled them (previous checkin) Modified: pypy/dist/pypy/translator/js/test/runtest.py ============================================================================== --- pypy/dist/pypy/translator/js/test/runtest.py (original) +++ pypy/dist/pypy/translator/js/test/runtest.py Wed Dec 13 21:30:52 2006 @@ -13,6 +13,7 @@ from pypy.conftest import option from pypy.rpython.test.tool import BaseRtypingTest, OORtypeMixin from pypy.translator.transformer.debug import DebugTransformer +from pypy.rlib.nonconst import NonConstant log = log.runtest use_browsertest = conftest.option.browser @@ -39,8 +40,8 @@ ann.build_types(function, annotations) if debug_transform: DebugTransformer(t).transform_all() - if view or option.view: - t.view() + if view or option.view: + t.view() t.buildrtyper(type_system="ootype").specialize() if view or option.view: @@ -141,20 +142,17 @@ # self._ann = ann # self._cli_func = compile_function(fn, ann) # return self._cli_func - - # XXX this will capture and use constant values - # for some test, for example reused from rpython/test - # it may result in annotation failures - # because some paths are not considered! - # that's what is provoking the failures - # in test_rpython - def f(): - res = fn(*args) + source = py.code.Source(""" + def %s(): + from pypy.rlib.nonconst import NonConstant + res = fn(%s) if isinstance(res, type(None)): return None else: - return str(res) - return compile_function(f, []) + return str(res)""" + % (fn.func_name, ",".join(["NonConstant(%s)" % i for i in args]))) + exec source.compile() in locals() + return compile_function(locals()[fn.func_name], []) def interpret(self, fn, args): #def f(args): From pedronis at codespeak.net Wed Dec 13 21:42:22 2006 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Wed, 13 Dec 2006 21:42:22 +0100 (CET) Subject: [pypy-svn] r35703 - pypy/dist/pypy/doc Message-ID: <20061213204222.2CF811008D@code0.codespeak.net> Author: pedronis Date: Wed Dec 13 21:42:20 2006 New Revision: 35703 Modified: pypy/dist/pypy/doc/draft-jit-outline.txt Log: fix ReST Modified: pypy/dist/pypy/doc/draft-jit-outline.txt ============================================================================== --- pypy/dist/pypy/doc/draft-jit-outline.txt (original) +++ pypy/dist/pypy/doc/draft-jit-outline.txt Wed Dec 13 21:42:20 2006 @@ -258,21 +258,21 @@ pc += 1 return acc -``s`` here is an input program, simply a string of "+" or "-", x and y -are integer input arguments. +``s`` here is an input program, simply a string of ``'+'`` or ``'-'``, ``x`` +and ``y`` are integer input arguments. The annotation of ``op = hint(op, concrete=True)`` will follow the dependencies of the argument ``op``, which is the result of ``op = -s[pc]``, so both ``s``and ``pc`` will be marked green. ``x``, ``y`` +s[pc]``, so both ``s`` and ``pc`` will be marked green. ``x``, ``y`` and ``acc`` will stay red. The result ``op`` compared to the possible "instructions" will also be -green. Because ``s``is green also ``len(s)`` will be. +green. Because ``s`` is green also ``len(s)`` will be. Using this information the *timeshifting* of the ``ll_plus_minus``, should be able to produce code that unfolds the loop and respectively folds instruction dispatching (the ifs) at compile-time, because the -while condition, the ``pc``increment, and the dispatching are +while condition, the ``pc`` increment, and the dispatching are operations among only greens (constants are green by default). Calls From arigo at codespeak.net Wed Dec 13 21:43:37 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 13 Dec 2006 21:43:37 +0100 (CET) Subject: [pypy-svn] r35704 - pypy/dist/pypy/interpreter/astcompiler Message-ID: <20061213204337.453351009F@code0.codespeak.net> Author: arigo Date: Wed Dec 13 21:43:32 2006 New Revision: 35704 Modified: pypy/dist/pypy/interpreter/astcompiler/ast.py pypy/dist/pypy/interpreter/astcompiler/ast.txt pypy/dist/pypy/interpreter/astcompiler/astgen.py Log: Replace all these getattr() + Arguments() + call_args() with just call_method(). Modified: pypy/dist/pypy/interpreter/astcompiler/ast.py ============================================================================== --- pypy/dist/pypy/interpreter/astcompiler/ast.py (original) +++ pypy/dist/pypy/interpreter/astcompiler/ast.py Wed Dec 13 21:43:32 2006 @@ -7,7 +7,6 @@ from pypy.interpreter.baseobjspace import Wrappable from pypy.interpreter.typedef import TypeDef, GetSetProperty, interp_attrproperty from pypy.interpreter.gateway import interp2app, W_Root, ObjSpace -from pypy.interpreter.argument import Arguments from pypy.interpreter.error import OperationError def flatten(list): @@ -67,14 +66,10 @@ return space.newlist( [ space.wrap( it ) for it in lst ] ) def descr_node_accept( space, w_self, w_visitor ): - w_callable = space.getattr(w_visitor, space.wrap('visitNode')) - args = Arguments(space, [ w_self ]) - return space.call_args( w_callable, args ) + return space.call_method( w_visitor, 'visitNode', w_self ) def descr_node_mutate(space, w_self, w_visitor): - w_visitNode = space.getattr(w_visitor, space.wrap("visitNode")) - w_visitNode_args = Arguments(space, [ w_self ]) - return space.call_args(w_visitNode, w_visitNode_args) + return space.call_method(w_visitor, 'visitNode', w_self) def descr_Node_new(space, w_subtype, lineno=-1): node = space.allocate_instance(Node, w_subtype) @@ -132,20 +127,14 @@ return space.wrap(self) def descr_expression_accept(space, w_self, w_visitor): - w_callable = space.getattr(w_visitor, space.wrap("visitExpression")) - args = Arguments(space, [ w_self ]) - return space.call_args(w_callable, args) + return space.call_method(w_visitor, 'visitExpression', w_self) def descr_expression_mutate(space, w_self, w_visitor): w_node = space.getattr(w_self, space.wrap("node")) - w_mutate_node = space.getattr(w_node, space.wrap("mutate")) - w_mutate_node_args = Arguments(space, [ w_visitor ]) - w_new_node = space.call_args(w_mutate_node, w_mutate_node_args) + w_new_node = space.call_method(w_node, "mutate", w_visitor) space.setattr(w_self, space.wrap("node"), w_new_node) - w_visitExpression = space.getattr(w_visitor, space.wrap("visitExpression")) - w_visitExpression_args = Arguments(space, [ w_self ]) - return space.call_args(w_visitExpression, w_visitExpression_args) + return space.call_method(w_visitor, "visitExpression", w_self) Expression.typedef = TypeDef('Expression', Node.typedef, __new__ = interp2app(descr_expression_new, unwrap_spec=[ObjSpace, W_Root, W_Root, int]), @@ -184,14 +173,10 @@ return space.wrap(self) def descr_AbstractFunction_accept( space, w_self, w_visitor): - w_callable = space.getattr(w_visitor, space.wrap('visitAbstractFunction')) - args = Arguments(space, [ w_self ]) - return space.call_args(w_callable, args) + return space.call_method(w_visitor, 'visitAbstractFunction', w_self) def descr_AbstractFunction_mutate(space, w_self, w_visitor): - w_visitAbstractFunction = space.getattr(w_visitor, space.wrap("visitAbstractFunction")) - w_visitAbstractFunction_args = Arguments(space, [ w_self ]) - return space.call_args(w_visitAbstractFunction, w_visitAbstractFunction_args) + return space.call_method(w_visitor, "visitAbstractFunction", w_self) AbstractFunction.typedef = TypeDef('AbstractFunction', Node.typedef, __new__ = interp2app(descr_AbstractFunction_new, unwrap_spec=[ObjSpace, W_Root, int]), @@ -227,14 +212,10 @@ return space.wrap(self) def descr_AbstractTest_accept( space, w_self, w_visitor): - w_callable = space.getattr(w_visitor, space.wrap('visitAbstractTest')) - args = Arguments(space, [ w_self ]) - return space.call_args(w_callable, args) + return space.call_method(w_visitor, 'visitAbstractTest', w_self) def descr_AbstractTest_mutate(space, w_self, w_visitor): - w_visitAbstractTest = space.getattr(w_visitor, space.wrap("visitAbstractTest")) - w_visitAbstractTest_args = Arguments(space, [ w_self ]) - return space.call_args(w_visitAbstractTest, w_visitAbstractTest_args) + return space.call_method(w_visitor, "visitAbstractTest", w_self) AbstractTest.typedef = TypeDef('AbstractTest', Node.typedef, __new__ = interp2app(descr_AbstractTest_new, unwrap_spec=[ObjSpace, W_Root, int]), @@ -270,14 +251,10 @@ return space.wrap(self) def descr_BinaryOp_accept( space, w_self, w_visitor): - w_callable = space.getattr(w_visitor, space.wrap('visitBinaryOp')) - args = Arguments(space, [ w_self ]) - return space.call_args(w_callable, args) + return space.call_method(w_visitor, 'visitBinaryOp', w_self) def descr_BinaryOp_mutate(space, w_self, w_visitor): - w_visitBinaryOp = space.getattr(w_visitor, space.wrap("visitBinaryOp")) - w_visitBinaryOp_args = Arguments(space, [ w_self ]) - return space.call_args(w_visitBinaryOp, w_visitBinaryOp_args) + return space.call_method(w_visitor, "visitBinaryOp", w_self) BinaryOp.typedef = TypeDef('BinaryOp', Node.typedef, __new__ = interp2app(descr_BinaryOp_new, unwrap_spec=[ObjSpace, W_Root, int]), @@ -329,26 +306,18 @@ return space.wrap(self) def descr_Add_accept( space, w_self, w_visitor): - w_callable = space.getattr(w_visitor, space.wrap('visitAdd')) - args = Arguments(space, [ w_self ]) - return space.call_args(w_callable, args) + return space.call_method(w_visitor, 'visitAdd', w_self) def descr_Add_mutate(space, w_self, w_visitor): w_left = space.getattr(w_self, space.wrap("left")) - w_mutate_left = space.getattr(w_left, space.wrap("mutate")) - w_mutate_left_args = Arguments(space, [ w_visitor ]) - w_new_left = space.call_args(w_mutate_left, w_mutate_left_args) + w_new_left = space.call_method(w_left, "mutate", w_visitor) space.setattr(w_self, space.wrap("left"), w_new_left) w_right = space.getattr(w_self, space.wrap("right")) - w_mutate_right = space.getattr(w_right, space.wrap("mutate")) - w_mutate_right_args = Arguments(space, [ w_visitor ]) - w_new_right = space.call_args(w_mutate_right, w_mutate_right_args) + w_new_right = space.call_method(w_right, "mutate", w_visitor) space.setattr(w_self, space.wrap("right"), w_new_right) - w_visitAdd = space.getattr(w_visitor, space.wrap("visitAdd")) - w_visitAdd_args = Arguments(space, [ w_self ]) - return space.call_args(w_visitAdd, w_visitAdd_args) + return space.call_method(w_visitor, "visitAdd", w_self) Add.typedef = TypeDef('Add', BinaryOp.typedef, __new__ = interp2app(descr_Add_new, unwrap_spec=[ObjSpace, W_Root, W_Root, W_Root, int]), @@ -403,25 +372,19 @@ return space.wrap(self) def descr_And_accept( space, w_self, w_visitor): - w_callable = space.getattr(w_visitor, space.wrap('visitAnd')) - args = Arguments(space, [ w_self ]) - return space.call_args(w_callable, args) + return space.call_method(w_visitor, 'visitAnd', w_self) def descr_And_mutate(space, w_self, w_visitor): w_list = space.getattr(w_self, space.wrap("nodes")) list_w = space.unpackiterable(w_list) newlist_w = [] for w_item in list_w: - w_item_mutate = space.getattr(w_item, space.wrap("mutate")) - w_item_mutate_args = Arguments(space, [ w_visitor ]) - w_newitem = space.call_args(w_item_mutate, w_item_mutate_args) + w_newitem = space.call_method(w_item, "mutate", w_visitor) if not space.is_w(w_newitem, space.w_None): newlist_w.append(w_newitem) w_newlist = space.newlist(newlist_w) space.setattr(w_self, space.wrap("nodes"), w_newlist) - w_visitAnd = space.getattr(w_visitor, space.wrap("visitAnd")) - w_visitAnd_args = Arguments(space, [ w_self ]) - return space.call_args(w_visitAnd, w_visitAnd_args) + return space.call_method(w_visitor, "visitAnd", w_self) And.typedef = TypeDef('And', AbstractTest.typedef, __new__ = interp2app(descr_And_new, unwrap_spec=[ObjSpace, W_Root, W_Root, int]), @@ -480,20 +443,14 @@ return space.wrap(self) def descr_AssAttr_accept( space, w_self, w_visitor): - w_callable = space.getattr(w_visitor, space.wrap('visitAssAttr')) - args = Arguments(space, [ w_self ]) - return space.call_args(w_callable, args) + return space.call_method(w_visitor, 'visitAssAttr', w_self) def descr_AssAttr_mutate(space, w_self, w_visitor): w_expr = space.getattr(w_self, space.wrap("expr")) - w_mutate_expr = space.getattr(w_expr, space.wrap("mutate")) - w_mutate_expr_args = Arguments(space, [ w_visitor ]) - w_new_expr = space.call_args(w_mutate_expr, w_mutate_expr_args) + w_new_expr = space.call_method(w_expr, "mutate", w_visitor) space.setattr(w_self, space.wrap("expr"), w_new_expr) - w_visitAssAttr = space.getattr(w_visitor, space.wrap("visitAssAttr")) - w_visitAssAttr_args = Arguments(space, [ w_self ]) - return space.call_args(w_visitAssAttr, w_visitAssAttr_args) + return space.call_method(w_visitor, "visitAssAttr", w_self) AssAttr.typedef = TypeDef('AssAttr', Node.typedef, __new__ = interp2app(descr_AssAttr_new, unwrap_spec=[ObjSpace, W_Root, W_Root, W_Root, W_Root, int]), @@ -532,14 +489,10 @@ return space.wrap(self) def descr_AssSeq_accept( space, w_self, w_visitor): - w_callable = space.getattr(w_visitor, space.wrap('visitAssSeq')) - args = Arguments(space, [ w_self ]) - return space.call_args(w_callable, args) + return space.call_method(w_visitor, 'visitAssSeq', w_self) def descr_AssSeq_mutate(space, w_self, w_visitor): - w_visitAssSeq = space.getattr(w_visitor, space.wrap("visitAssSeq")) - w_visitAssSeq_args = Arguments(space, [ w_self ]) - return space.call_args(w_visitAssSeq, w_visitAssSeq_args) + return space.call_method(w_visitor, "visitAssSeq", w_self) AssSeq.typedef = TypeDef('AssSeq', Node.typedef, __new__ = interp2app(descr_AssSeq_new, unwrap_spec=[ObjSpace, W_Root, int]), @@ -592,25 +545,19 @@ return space.wrap(self) def descr_AssList_accept( space, w_self, w_visitor): - w_callable = space.getattr(w_visitor, space.wrap('visitAssList')) - args = Arguments(space, [ w_self ]) - return space.call_args(w_callable, args) + return space.call_method(w_visitor, 'visitAssList', w_self) def descr_AssList_mutate(space, w_self, w_visitor): w_list = space.getattr(w_self, space.wrap("nodes")) list_w = space.unpackiterable(w_list) newlist_w = [] for w_item in list_w: - w_item_mutate = space.getattr(w_item, space.wrap("mutate")) - w_item_mutate_args = Arguments(space, [ w_visitor ]) - w_newitem = space.call_args(w_item_mutate, w_item_mutate_args) + w_newitem = space.call_method(w_item, "mutate", w_visitor) if not space.is_w(w_newitem, space.w_None): newlist_w.append(w_newitem) w_newlist = space.newlist(newlist_w) space.setattr(w_self, space.wrap("nodes"), w_newlist) - w_visitAssList = space.getattr(w_visitor, space.wrap("visitAssList")) - w_visitAssList_args = Arguments(space, [ w_self ]) - return space.call_args(w_visitAssList, w_visitAssList_args) + return space.call_method(w_visitor, "visitAssList", w_self) AssList.typedef = TypeDef('AssList', AssSeq.typedef, __new__ = interp2app(descr_AssList_new, unwrap_spec=[ObjSpace, W_Root, W_Root, int]), @@ -661,14 +608,10 @@ return space.wrap(self) def descr_AssName_accept( space, w_self, w_visitor): - w_callable = space.getattr(w_visitor, space.wrap('visitAssName')) - args = Arguments(space, [ w_self ]) - return space.call_args(w_callable, args) + return space.call_method(w_visitor, 'visitAssName', w_self) def descr_AssName_mutate(space, w_self, w_visitor): - w_visitAssName = space.getattr(w_visitor, space.wrap("visitAssName")) - w_visitAssName_args = Arguments(space, [ w_self ]) - return space.call_args(w_visitAssName, w_visitAssName_args) + return space.call_method(w_visitor, "visitAssName", w_self) AssName.typedef = TypeDef('AssName', Node.typedef, __new__ = interp2app(descr_AssName_new, unwrap_spec=[ObjSpace, W_Root, W_Root, W_Root, int]), @@ -737,25 +680,19 @@ return space.wrap(self) def descr_AssTuple_accept( space, w_self, w_visitor): - w_callable = space.getattr(w_visitor, space.wrap('visitAssTuple')) - args = Arguments(space, [ w_self ]) - return space.call_args(w_callable, args) + return space.call_method(w_visitor, 'visitAssTuple', w_self) def descr_AssTuple_mutate(space, w_self, w_visitor): w_list = space.getattr(w_self, space.wrap("nodes")) list_w = space.unpackiterable(w_list) newlist_w = [] for w_item in list_w: - w_item_mutate = space.getattr(w_item, space.wrap("mutate")) - w_item_mutate_args = Arguments(space, [ w_visitor ]) - w_newitem = space.call_args(w_item_mutate, w_item_mutate_args) + w_newitem = space.call_method(w_item, "mutate", w_visitor) if not space.is_w(w_newitem, space.w_None): newlist_w.append(w_newitem) w_newlist = space.newlist(newlist_w) space.setattr(w_self, space.wrap("nodes"), w_newlist) - w_visitAssTuple = space.getattr(w_visitor, space.wrap("visitAssTuple")) - w_visitAssTuple_args = Arguments(space, [ w_self ]) - return space.call_args(w_visitAssTuple, w_visitAssTuple_args) + return space.call_method(w_visitor, "visitAssTuple", w_self) AssTuple.typedef = TypeDef('AssTuple', AssSeq.typedef, __new__ = interp2app(descr_AssTuple_new, unwrap_spec=[ObjSpace, W_Root, W_Root, int]), @@ -819,27 +756,19 @@ return space.wrap(self) def descr_Assert_accept( space, w_self, w_visitor): - w_callable = space.getattr(w_visitor, space.wrap('visitAssert')) - args = Arguments(space, [ w_self ]) - return space.call_args(w_callable, args) + return space.call_method(w_visitor, 'visitAssert', w_self) def descr_Assert_mutate(space, w_self, w_visitor): w_test = space.getattr(w_self, space.wrap("test")) - w_mutate_test = space.getattr(w_test, space.wrap("mutate")) - w_mutate_test_args = Arguments(space, [ w_visitor ]) - w_new_test = space.call_args(w_mutate_test, w_mutate_test_args) + w_new_test = space.call_method(w_test, "mutate", w_visitor) space.setattr(w_self, space.wrap("test"), w_new_test) w_fail = space.getattr(w_self, space.wrap("fail")) if not space.is_w(w_fail, space.w_None): - w_mutate_fail = space.getattr(w_fail, space.wrap("mutate")) - w_mutate_fail_args = Arguments(space, [ w_visitor ]) - w_new_fail = space.call_args(w_mutate_fail, w_mutate_fail_args) + w_new_fail = space.call_method(w_fail, "mutate", w_visitor) space.setattr(w_self, space.wrap("fail"), w_new_fail) - w_visitAssert = space.getattr(w_visitor, space.wrap("visitAssert")) - w_visitAssert_args = Arguments(space, [ w_self ]) - return space.call_args(w_visitAssert, w_visitAssert_args) + return space.call_method(w_visitor, "visitAssert", w_self) Assert.typedef = TypeDef('Assert', Node.typedef, __new__ = interp2app(descr_Assert_new, unwrap_spec=[ObjSpace, W_Root, W_Root, W_Root, int]), @@ -906,31 +835,23 @@ return space.wrap(self) def descr_Assign_accept( space, w_self, w_visitor): - w_callable = space.getattr(w_visitor, space.wrap('visitAssign')) - args = Arguments(space, [ w_self ]) - return space.call_args(w_callable, args) + return space.call_method(w_visitor, 'visitAssign', w_self) def descr_Assign_mutate(space, w_self, w_visitor): w_list = space.getattr(w_self, space.wrap("nodes")) list_w = space.unpackiterable(w_list) newlist_w = [] for w_item in list_w: - w_item_mutate = space.getattr(w_item, space.wrap("mutate")) - w_item_mutate_args = Arguments(space, [ w_visitor ]) - w_newitem = space.call_args(w_item_mutate, w_item_mutate_args) + w_newitem = space.call_method(w_item, "mutate", w_visitor) if not space.is_w(w_newitem, space.w_None): newlist_w.append(w_newitem) w_newlist = space.newlist(newlist_w) space.setattr(w_self, space.wrap("nodes"), w_newlist) w_expr = space.getattr(w_self, space.wrap("expr")) - w_mutate_expr = space.getattr(w_expr, space.wrap("mutate")) - w_mutate_expr_args = Arguments(space, [ w_visitor ]) - w_new_expr = space.call_args(w_mutate_expr, w_mutate_expr_args) + w_new_expr = space.call_method(w_expr, "mutate", w_visitor) space.setattr(w_self, space.wrap("expr"), w_new_expr) - w_visitAssign = space.getattr(w_visitor, space.wrap("visitAssign")) - w_visitAssign_args = Arguments(space, [ w_self ]) - return space.call_args(w_visitAssign, w_visitAssign_args) + return space.call_method(w_visitor, "visitAssign", w_self) Assign.typedef = TypeDef('Assign', Node.typedef, __new__ = interp2app(descr_Assign_new, unwrap_spec=[ObjSpace, W_Root, W_Root, W_Root, int]), @@ -991,26 +912,18 @@ return space.wrap(self) def descr_AugAssign_accept( space, w_self, w_visitor): - w_callable = space.getattr(w_visitor, space.wrap('visitAugAssign')) - args = Arguments(space, [ w_self ]) - return space.call_args(w_callable, args) + return space.call_method(w_visitor, 'visitAugAssign', w_self) def descr_AugAssign_mutate(space, w_self, w_visitor): w_node = space.getattr(w_self, space.wrap("node")) - w_mutate_node = space.getattr(w_node, space.wrap("mutate")) - w_mutate_node_args = Arguments(space, [ w_visitor ]) - w_new_node = space.call_args(w_mutate_node, w_mutate_node_args) + w_new_node = space.call_method(w_node, "mutate", w_visitor) space.setattr(w_self, space.wrap("node"), w_new_node) w_expr = space.getattr(w_self, space.wrap("expr")) - w_mutate_expr = space.getattr(w_expr, space.wrap("mutate")) - w_mutate_expr_args = Arguments(space, [ w_visitor ]) - w_new_expr = space.call_args(w_mutate_expr, w_mutate_expr_args) + w_new_expr = space.call_method(w_expr, "mutate", w_visitor) space.setattr(w_self, space.wrap("expr"), w_new_expr) - w_visitAugAssign = space.getattr(w_visitor, space.wrap("visitAugAssign")) - w_visitAugAssign_args = Arguments(space, [ w_self ]) - return space.call_args(w_visitAugAssign, w_visitAugAssign_args) + return space.call_method(w_visitor, "visitAugAssign", w_self) AugAssign.typedef = TypeDef('AugAssign', Node.typedef, __new__ = interp2app(descr_AugAssign_new, unwrap_spec=[ObjSpace, W_Root, W_Root, W_Root, W_Root, int]), @@ -1049,14 +962,10 @@ return space.wrap(self) def descr_UnaryOp_accept( space, w_self, w_visitor): - w_callable = space.getattr(w_visitor, space.wrap('visitUnaryOp')) - args = Arguments(space, [ w_self ]) - return space.call_args(w_callable, args) + return space.call_method(w_visitor, 'visitUnaryOp', w_self) def descr_UnaryOp_mutate(space, w_self, w_visitor): - w_visitUnaryOp = space.getattr(w_visitor, space.wrap("visitUnaryOp")) - w_visitUnaryOp_args = Arguments(space, [ w_self ]) - return space.call_args(w_visitUnaryOp, w_visitUnaryOp_args) + return space.call_method(w_visitor, "visitUnaryOp", w_self) UnaryOp.typedef = TypeDef('UnaryOp', Node.typedef, __new__ = interp2app(descr_UnaryOp_new, unwrap_spec=[ObjSpace, W_Root, int]), @@ -1100,20 +1009,14 @@ return space.wrap(self) def descr_Backquote_accept( space, w_self, w_visitor): - w_callable = space.getattr(w_visitor, space.wrap('visitBackquote')) - args = Arguments(space, [ w_self ]) - return space.call_args(w_callable, args) + return space.call_method(w_visitor, 'visitBackquote', w_self) def descr_Backquote_mutate(space, w_self, w_visitor): w_expr = space.getattr(w_self, space.wrap("expr")) - w_mutate_expr = space.getattr(w_expr, space.wrap("mutate")) - w_mutate_expr_args = Arguments(space, [ w_visitor ]) - w_new_expr = space.call_args(w_mutate_expr, w_mutate_expr_args) + w_new_expr = space.call_method(w_expr, "mutate", w_visitor) space.setattr(w_self, space.wrap("expr"), w_new_expr) - w_visitBackquote = space.getattr(w_visitor, space.wrap("visitBackquote")) - w_visitBackquote_args = Arguments(space, [ w_self ]) - return space.call_args(w_visitBackquote, w_visitBackquote_args) + return space.call_method(w_visitor, "visitBackquote", w_self) Backquote.typedef = TypeDef('Backquote', UnaryOp.typedef, __new__ = interp2app(descr_Backquote_new, unwrap_spec=[ObjSpace, W_Root, W_Root, int]), @@ -1150,14 +1053,10 @@ return space.wrap(self) def descr_BitOp_accept( space, w_self, w_visitor): - w_callable = space.getattr(w_visitor, space.wrap('visitBitOp')) - args = Arguments(space, [ w_self ]) - return space.call_args(w_callable, args) + return space.call_method(w_visitor, 'visitBitOp', w_self) def descr_BitOp_mutate(space, w_self, w_visitor): - w_visitBitOp = space.getattr(w_visitor, space.wrap("visitBitOp")) - w_visitBitOp_args = Arguments(space, [ w_self ]) - return space.call_args(w_visitBitOp, w_visitBitOp_args) + return space.call_method(w_visitor, "visitBitOp", w_self) BitOp.typedef = TypeDef('BitOp', Node.typedef, __new__ = interp2app(descr_BitOp_new, unwrap_spec=[ObjSpace, W_Root, int]), @@ -1210,25 +1109,19 @@ return space.wrap(self) def descr_Bitand_accept( space, w_self, w_visitor): - w_callable = space.getattr(w_visitor, space.wrap('visitBitand')) - args = Arguments(space, [ w_self ]) - return space.call_args(w_callable, args) + return space.call_method(w_visitor, 'visitBitand', w_self) def descr_Bitand_mutate(space, w_self, w_visitor): w_list = space.getattr(w_self, space.wrap("nodes")) list_w = space.unpackiterable(w_list) newlist_w = [] for w_item in list_w: - w_item_mutate = space.getattr(w_item, space.wrap("mutate")) - w_item_mutate_args = Arguments(space, [ w_visitor ]) - w_newitem = space.call_args(w_item_mutate, w_item_mutate_args) + w_newitem = space.call_method(w_item, "mutate", w_visitor) if not space.is_w(w_newitem, space.w_None): newlist_w.append(w_newitem) w_newlist = space.newlist(newlist_w) space.setattr(w_self, space.wrap("nodes"), w_newlist) - w_visitBitand = space.getattr(w_visitor, space.wrap("visitBitand")) - w_visitBitand_args = Arguments(space, [ w_self ]) - return space.call_args(w_visitBitand, w_visitBitand_args) + return space.call_method(w_visitor, "visitBitand", w_self) Bitand.typedef = TypeDef('Bitand', BitOp.typedef, __new__ = interp2app(descr_Bitand_new, unwrap_spec=[ObjSpace, W_Root, W_Root, int]), @@ -1282,25 +1175,19 @@ return space.wrap(self) def descr_Bitor_accept( space, w_self, w_visitor): - w_callable = space.getattr(w_visitor, space.wrap('visitBitor')) - args = Arguments(space, [ w_self ]) - return space.call_args(w_callable, args) + return space.call_method(w_visitor, 'visitBitor', w_self) def descr_Bitor_mutate(space, w_self, w_visitor): w_list = space.getattr(w_self, space.wrap("nodes")) list_w = space.unpackiterable(w_list) newlist_w = [] for w_item in list_w: - w_item_mutate = space.getattr(w_item, space.wrap("mutate")) - w_item_mutate_args = Arguments(space, [ w_visitor ]) - w_newitem = space.call_args(w_item_mutate, w_item_mutate_args) + w_newitem = space.call_method(w_item, "mutate", w_visitor) if not space.is_w(w_newitem, space.w_None): newlist_w.append(w_newitem) w_newlist = space.newlist(newlist_w) space.setattr(w_self, space.wrap("nodes"), w_newlist) - w_visitBitor = space.getattr(w_visitor, space.wrap("visitBitor")) - w_visitBitor_args = Arguments(space, [ w_self ]) - return space.call_args(w_visitBitor, w_visitBitor_args) + return space.call_method(w_visitor, "visitBitor", w_self) Bitor.typedef = TypeDef('Bitor', BitOp.typedef, __new__ = interp2app(descr_Bitor_new, unwrap_spec=[ObjSpace, W_Root, W_Root, int]), @@ -1354,25 +1241,19 @@ return space.wrap(self) def descr_Bitxor_accept( space, w_self, w_visitor): - w_callable = space.getattr(w_visitor, space.wrap('visitBitxor')) - args = Arguments(space, [ w_self ]) - return space.call_args(w_callable, args) + return space.call_method(w_visitor, 'visitBitxor', w_self) def descr_Bitxor_mutate(space, w_self, w_visitor): w_list = space.getattr(w_self, space.wrap("nodes")) list_w = space.unpackiterable(w_list) newlist_w = [] for w_item in list_w: - w_item_mutate = space.getattr(w_item, space.wrap("mutate")) - w_item_mutate_args = Arguments(space, [ w_visitor ]) - w_newitem = space.call_args(w_item_mutate, w_item_mutate_args) + w_newitem = space.call_method(w_item, "mutate", w_visitor) if not space.is_w(w_newitem, space.w_None): newlist_w.append(w_newitem) w_newlist = space.newlist(newlist_w) space.setattr(w_self, space.wrap("nodes"), w_newlist) - w_visitBitxor = space.getattr(w_visitor, space.wrap("visitBitxor")) - w_visitBitxor_args = Arguments(space, [ w_self ]) - return space.call_args(w_visitBitxor, w_visitBitxor_args) + return space.call_method(w_visitor, "visitBitxor", w_self) Bitxor.typedef = TypeDef('Bitxor', BitOp.typedef, __new__ = interp2app(descr_Bitxor_new, unwrap_spec=[ObjSpace, W_Root, W_Root, int]), @@ -1409,14 +1290,10 @@ return space.wrap(self) def descr_Break_accept( space, w_self, w_visitor): - w_callable = space.getattr(w_visitor, space.wrap('visitBreak')) - args = Arguments(space, [ w_self ]) - return space.call_args(w_callable, args) + return space.call_method(w_visitor, 'visitBreak', w_self) def descr_Break_mutate(space, w_self, w_visitor): - w_visitBreak = space.getattr(w_visitor, space.wrap("visitBreak")) - w_visitBreak_args = Arguments(space, [ w_self ]) - return space.call_args(w_visitBreak, w_visitBreak_args) + return space.call_method(w_visitor, "visitBreak", w_self) Break.typedef = TypeDef('Break', Node.typedef, __new__ = interp2app(descr_Break_new, unwrap_spec=[ObjSpace, W_Root, int]), @@ -1511,45 +1388,33 @@ return space.wrap(self) def descr_CallFunc_accept( space, w_self, w_visitor): - w_callable = space.getattr(w_visitor, space.wrap('visitCallFunc')) - args = Arguments(space, [ w_self ]) - return space.call_args(w_callable, args) + return space.call_method(w_visitor, 'visitCallFunc', w_self) def descr_CallFunc_mutate(space, w_self, w_visitor): w_node = space.getattr(w_self, space.wrap("node")) - w_mutate_node = space.getattr(w_node, space.wrap("mutate")) - w_mutate_node_args = Arguments(space, [ w_visitor ]) - w_new_node = space.call_args(w_mutate_node, w_mutate_node_args) + w_new_node = space.call_method(w_node, "mutate", w_visitor) space.setattr(w_self, space.wrap("node"), w_new_node) w_list = space.getattr(w_self, space.wrap("args")) list_w = space.unpackiterable(w_list) newlist_w = [] for w_item in list_w: - w_item_mutate = space.getattr(w_item, space.wrap("mutate")) - w_item_mutate_args = Arguments(space, [ w_visitor ]) - w_newitem = space.call_args(w_item_mutate, w_item_mutate_args) + w_newitem = space.call_method(w_item, "mutate", w_visitor) if not space.is_w(w_newitem, space.w_None): newlist_w.append(w_newitem) w_newlist = space.newlist(newlist_w) space.setattr(w_self, space.wrap("args"), w_newlist) w_star_args = space.getattr(w_self, space.wrap("star_args")) if not space.is_w(w_star_args, space.w_None): - w_mutate_star_args = space.getattr(w_star_args, space.wrap("mutate")) - w_mutate_star_args_args = Arguments(space, [ w_visitor ]) - w_new_star_args = space.call_args(w_mutate_star_args, w_mutate_star_args_args) + w_new_star_args = space.call_method(w_star_args, "mutate", w_visitor) space.setattr(w_self, space.wrap("star_args"), w_new_star_args) w_dstar_args = space.getattr(w_self, space.wrap("dstar_args")) if not space.is_w(w_dstar_args, space.w_None): - w_mutate_dstar_args = space.getattr(w_dstar_args, space.wrap("mutate")) - w_mutate_dstar_args_args = Arguments(space, [ w_visitor ]) - w_new_dstar_args = space.call_args(w_mutate_dstar_args, w_mutate_dstar_args_args) + w_new_dstar_args = space.call_method(w_dstar_args, "mutate", w_visitor) space.setattr(w_self, space.wrap("dstar_args"), w_new_dstar_args) - w_visitCallFunc = space.getattr(w_visitor, space.wrap("visitCallFunc")) - w_visitCallFunc_args = Arguments(space, [ w_self ]) - return space.call_args(w_visitCallFunc, w_visitCallFunc_args) + return space.call_method(w_visitor, "visitCallFunc", w_self) CallFunc.typedef = TypeDef('CallFunc', Node.typedef, __new__ = interp2app(descr_CallFunc_new, unwrap_spec=[ObjSpace, W_Root, W_Root, W_Root, W_Root, W_Root, int]), @@ -1635,31 +1500,23 @@ return space.wrap(self) def descr_Class_accept( space, w_self, w_visitor): - w_callable = space.getattr(w_visitor, space.wrap('visitClass')) - args = Arguments(space, [ w_self ]) - return space.call_args(w_callable, args) + return space.call_method(w_visitor, 'visitClass', w_self) def descr_Class_mutate(space, w_self, w_visitor): w_list = space.getattr(w_self, space.wrap("bases")) list_w = space.unpackiterable(w_list) newlist_w = [] for w_item in list_w: - w_item_mutate = space.getattr(w_item, space.wrap("mutate")) - w_item_mutate_args = Arguments(space, [ w_visitor ]) - w_newitem = space.call_args(w_item_mutate, w_item_mutate_args) + w_newitem = space.call_method(w_item, "mutate", w_visitor) if not space.is_w(w_newitem, space.w_None): newlist_w.append(w_newitem) w_newlist = space.newlist(newlist_w) space.setattr(w_self, space.wrap("bases"), w_newlist) w_code = space.getattr(w_self, space.wrap("code")) - w_mutate_code = space.getattr(w_code, space.wrap("mutate")) - w_mutate_code_args = Arguments(space, [ w_visitor ]) - w_new_code = space.call_args(w_mutate_code, w_mutate_code_args) + w_new_code = space.call_method(w_code, "mutate", w_visitor) space.setattr(w_self, space.wrap("code"), w_new_code) - w_visitClass = space.getattr(w_visitor, space.wrap("visitClass")) - w_visitClass_args = Arguments(space, [ w_self ]) - return space.call_args(w_visitClass, w_visitClass_args) + return space.call_method(w_visitor, "visitClass", w_self) Class.typedef = TypeDef('Class', Node.typedef, __new__ = interp2app(descr_Class_new, unwrap_spec=[ObjSpace, W_Root, W_Root, W_Root, W_Root, W_Root, int]), @@ -1745,15 +1602,11 @@ def descr_Compare_accept( space, w_self, w_visitor): - w_callable = space.getattr(w_visitor, space.wrap('visitCompare')) - args = Arguments(space, [ w_self ]) - return space.call_args(w_callable, args) + return space.call_method(w_visitor, 'visitCompare', w_self) def descr_Compare_mutate(space, w_self, w_visitor): w_expr = space.getattr(w_self, space.wrap("expr")) - w_mutate_expr = space.getattr(w_expr, space.wrap("mutate")) - w_mutate_expr_args = Arguments(space, [ w_visitor ]) - w_new_expr = space.call_args(w_mutate_expr, w_mutate_expr_args) + w_new_expr = space.call_method(w_expr, "mutate", w_visitor) space.setattr(w_self, space.wrap("expr"), w_new_expr) w_list = space.getattr(w_self, space.wrap("ops")) @@ -1762,16 +1615,12 @@ for w_item in list_w: w_opname, w_node = space.unpackiterable(w_item, 2) - w_node_mutate = space.getattr(w_node, space.wrap("mutate")) - w_node_mutate_args = Arguments(space, [ w_visitor ]) - w_newnode = space.call_args(w_node_mutate, w_node_mutate_args) + w_newnode = space.call_method(w_node, "mutate", w_visitor) newlist_w.append(space.newtuple([w_opname, w_newnode])) w_newlist = space.newlist(newlist_w) space.setattr(w_self, space.wrap("ops"), w_newlist) - w_visitCompare = space.getattr(w_visitor, space.wrap("visitCompare")) - w_visitCompare_args = Arguments(space, [ w_self ]) - return space.call_args(w_visitCompare, w_visitCompare_args) + return space.call_method(w_visitor, "visitCompare", w_self) @@ -1836,32 +1685,22 @@ return space.wrap(self) def descr_CondExpr_accept( space, w_self, w_visitor): - w_callable = space.getattr(w_visitor, space.wrap('visitCondExpr')) - args = Arguments(space, [ w_self ]) - return space.call_args(w_callable, args) + return space.call_method(w_visitor, 'visitCondExpr', w_self) def descr_CondExpr_mutate(space, w_self, w_visitor): w_test = space.getattr(w_self, space.wrap("test")) - w_mutate_test = space.getattr(w_test, space.wrap("mutate")) - w_mutate_test_args = Arguments(space, [ w_visitor ]) - w_new_test = space.call_args(w_mutate_test, w_mutate_test_args) + w_new_test = space.call_method(w_test, "mutate", w_visitor) space.setattr(w_self, space.wrap("test"), w_new_test) w_true_expr = space.getattr(w_self, space.wrap("true_expr")) - w_mutate_true_expr = space.getattr(w_true_expr, space.wrap("mutate")) - w_mutate_true_expr_args = Arguments(space, [ w_visitor ]) - w_new_true_expr = space.call_args(w_mutate_true_expr, w_mutate_true_expr_args) + w_new_true_expr = space.call_method(w_true_expr, "mutate", w_visitor) space.setattr(w_self, space.wrap("true_expr"), w_new_true_expr) w_false_expr = space.getattr(w_self, space.wrap("false_expr")) - w_mutate_false_expr = space.getattr(w_false_expr, space.wrap("mutate")) - w_mutate_false_expr_args = Arguments(space, [ w_visitor ]) - w_new_false_expr = space.call_args(w_mutate_false_expr, w_mutate_false_expr_args) + w_new_false_expr = space.call_method(w_false_expr, "mutate", w_visitor) space.setattr(w_self, space.wrap("false_expr"), w_new_false_expr) - w_visitCondExpr = space.getattr(w_visitor, space.wrap("visitCondExpr")) - w_visitCondExpr_args = Arguments(space, [ w_self ]) - return space.call_args(w_visitCondExpr, w_visitCondExpr_args) + return space.call_method(w_visitor, "visitCondExpr", w_self) CondExpr.typedef = TypeDef('CondExpr', Node.typedef, __new__ = interp2app(descr_CondExpr_new, unwrap_spec=[ObjSpace, W_Root, W_Root, W_Root, W_Root, int]), @@ -1908,14 +1747,10 @@ return space.wrap(self) def descr_Const_accept( space, w_self, w_visitor): - w_callable = space.getattr(w_visitor, space.wrap('visitConst')) - args = Arguments(space, [ w_self ]) - return space.call_args(w_callable, args) + return space.call_method(w_visitor, 'visitConst', w_self) def descr_Const_mutate(space, w_self, w_visitor): - w_visitConst = space.getattr(w_visitor, space.wrap("visitConst")) - w_visitConst_args = Arguments(space, [ w_self ]) - return space.call_args(w_visitConst, w_visitConst_args) + return space.call_method(w_visitor, "visitConst", w_self) Const.typedef = TypeDef('Const', Node.typedef, __new__ = interp2app(descr_Const_new, unwrap_spec=[ObjSpace, W_Root, W_Root, int]), @@ -1952,14 +1787,10 @@ return space.wrap(self) def descr_Continue_accept( space, w_self, w_visitor): - w_callable = space.getattr(w_visitor, space.wrap('visitContinue')) - args = Arguments(space, [ w_self ]) - return space.call_args(w_callable, args) + return space.call_method(w_visitor, 'visitContinue', w_self) def descr_Continue_mutate(space, w_self, w_visitor): - w_visitContinue = space.getattr(w_visitor, space.wrap("visitContinue")) - w_visitContinue_args = Arguments(space, [ w_self ]) - return space.call_args(w_visitContinue, w_visitContinue_args) + return space.call_method(w_visitor, "visitContinue", w_self) Continue.typedef = TypeDef('Continue', Node.typedef, __new__ = interp2app(descr_Continue_new, unwrap_spec=[ObjSpace, W_Root, int]), @@ -2012,25 +1843,19 @@ return space.wrap(self) def descr_Decorators_accept( space, w_self, w_visitor): - w_callable = space.getattr(w_visitor, space.wrap('visitDecorators')) - args = Arguments(space, [ w_self ]) - return space.call_args(w_callable, args) + return space.call_method(w_visitor, 'visitDecorators', w_self) def descr_Decorators_mutate(space, w_self, w_visitor): w_list = space.getattr(w_self, space.wrap("nodes")) list_w = space.unpackiterable(w_list) newlist_w = [] for w_item in list_w: - w_item_mutate = space.getattr(w_item, space.wrap("mutate")) - w_item_mutate_args = Arguments(space, [ w_visitor ]) - w_newitem = space.call_args(w_item_mutate, w_item_mutate_args) + w_newitem = space.call_method(w_item, "mutate", w_visitor) if not space.is_w(w_newitem, space.w_None): newlist_w.append(w_newitem) w_newlist = space.newlist(newlist_w) space.setattr(w_self, space.wrap("nodes"), w_newlist) - w_visitDecorators = space.getattr(w_visitor, space.wrap("visitDecorators")) - w_visitDecorators_args = Arguments(space, [ w_self ]) - return space.call_args(w_visitDecorators, w_visitDecorators_args) + return space.call_method(w_visitor, "visitDecorators", w_self) Decorators.typedef = TypeDef('Decorators', Node.typedef, __new__ = interp2app(descr_Decorators_new, unwrap_spec=[ObjSpace, W_Root, W_Root, int]), @@ -2102,9 +1927,7 @@ def descr_Dict_accept( space, w_self, w_visitor): - w_callable = space.getattr(w_visitor, space.wrap('visitDict')) - args = Arguments(space, [ w_self ]) - return space.call_args(w_callable, args) + return space.call_method(w_visitor, 'visitDict', w_self) def descr_Dict_mutate(space, w_self, w_visitor): w_list = space.getattr(w_self, space.wrap("items")) @@ -2113,20 +1936,13 @@ for w_item in list_w: w_key, w_value = space.unpackiterable(w_item, 2) - w_key_mutate = space.getattr(w_key, space.wrap("mutate")) - w_key_mutate_args = Arguments(space, [ w_visitor ]) - w_newkey = space.call_args(w_key_mutate, w_key_mutate_args) - - w_value_mutate = space.getattr(w_value, space.wrap("mutate")) - w_value_mutate_args = Arguments(space, [ w_visitor ]) - w_newvalue = space.call_args(w_value_mutate, w_value_mutate_args) + w_newkey = space.call_method(w_key, "mutate", w_visitor) + w_newvalue = space.call_method(w_value, "mutate", w_visitor) newlist_w.append(space.newtuple([w_newkey, w_newvalue])) w_newlist = space.newlist(newlist_w) space.setattr(w_self, space.wrap("items"), w_newlist) - w_visitDict = space.getattr(w_visitor, space.wrap("visitDict")) - w_visitDict_args = Arguments(space, [ w_self ]) - return space.call_args(w_visitDict, w_visitDict_args) + return space.call_method(w_visitor, "visitDict", w_self) @@ -2173,20 +1989,14 @@ return space.wrap(self) def descr_Discard_accept( space, w_self, w_visitor): - w_callable = space.getattr(w_visitor, space.wrap('visitDiscard')) - args = Arguments(space, [ w_self ]) - return space.call_args(w_callable, args) + return space.call_method(w_visitor, 'visitDiscard', w_self) def descr_Discard_mutate(space, w_self, w_visitor): w_expr = space.getattr(w_self, space.wrap("expr")) - w_mutate_expr = space.getattr(w_expr, space.wrap("mutate")) - w_mutate_expr_args = Arguments(space, [ w_visitor ]) - w_new_expr = space.call_args(w_mutate_expr, w_mutate_expr_args) + w_new_expr = space.call_method(w_expr, "mutate", w_visitor) space.setattr(w_self, space.wrap("expr"), w_new_expr) - w_visitDiscard = space.getattr(w_visitor, space.wrap("visitDiscard")) - w_visitDiscard_args = Arguments(space, [ w_self ]) - return space.call_args(w_visitDiscard, w_visitDiscard_args) + return space.call_method(w_visitor, "visitDiscard", w_self) Discard.typedef = TypeDef('Discard', Node.typedef, __new__ = interp2app(descr_Discard_new, unwrap_spec=[ObjSpace, W_Root, W_Root, int]), @@ -2239,26 +2049,18 @@ return space.wrap(self) def descr_Div_accept( space, w_self, w_visitor): - w_callable = space.getattr(w_visitor, space.wrap('visitDiv')) - args = Arguments(space, [ w_self ]) - return space.call_args(w_callable, args) + return space.call_method(w_visitor, 'visitDiv', w_self) def descr_Div_mutate(space, w_self, w_visitor): w_left = space.getattr(w_self, space.wrap("left")) - w_mutate_left = space.getattr(w_left, space.wrap("mutate")) - w_mutate_left_args = Arguments(space, [ w_visitor ]) - w_new_left = space.call_args(w_mutate_left, w_mutate_left_args) + w_new_left = space.call_method(w_left, "mutate", w_visitor) space.setattr(w_self, space.wrap("left"), w_new_left) w_right = space.getattr(w_self, space.wrap("right")) - w_mutate_right = space.getattr(w_right, space.wrap("mutate")) - w_mutate_right_args = Arguments(space, [ w_visitor ]) - w_new_right = space.call_args(w_mutate_right, w_mutate_right_args) + w_new_right = space.call_method(w_right, "mutate", w_visitor) space.setattr(w_self, space.wrap("right"), w_new_right) - w_visitDiv = space.getattr(w_visitor, space.wrap("visitDiv")) - w_visitDiv_args = Arguments(space, [ w_self ]) - return space.call_args(w_visitDiv, w_visitDiv_args) + return space.call_method(w_visitor, "visitDiv", w_self) Div.typedef = TypeDef('Div', BinaryOp.typedef, __new__ = interp2app(descr_Div_new, unwrap_spec=[ObjSpace, W_Root, W_Root, W_Root, int]), @@ -2296,14 +2098,10 @@ return space.wrap(self) def descr_Ellipsis_accept( space, w_self, w_visitor): - w_callable = space.getattr(w_visitor, space.wrap('visitEllipsis')) - args = Arguments(space, [ w_self ]) - return space.call_args(w_callable, args) + return space.call_method(w_visitor, 'visitEllipsis', w_self) def descr_Ellipsis_mutate(space, w_self, w_visitor): - w_visitEllipsis = space.getattr(w_visitor, space.wrap("visitEllipsis")) - w_visitEllipsis_args = Arguments(space, [ w_self ]) - return space.call_args(w_visitEllipsis, w_visitEllipsis_args) + return space.call_method(w_visitor, "visitEllipsis", w_self) Ellipsis.typedef = TypeDef('Ellipsis', Node.typedef, __new__ = interp2app(descr_Ellipsis_new, unwrap_spec=[ObjSpace, W_Root, int]), @@ -2381,34 +2179,24 @@ return space.wrap(self) def descr_Exec_accept( space, w_self, w_visitor): - w_callable = space.getattr(w_visitor, space.wrap('visitExec')) - args = Arguments(space, [ w_self ]) - return space.call_args(w_callable, args) + return space.call_method(w_visitor, 'visitExec', w_self) def descr_Exec_mutate(space, w_self, w_visitor): w_expr = space.getattr(w_self, space.wrap("expr")) - w_mutate_expr = space.getattr(w_expr, space.wrap("mutate")) - w_mutate_expr_args = Arguments(space, [ w_visitor ]) - w_new_expr = space.call_args(w_mutate_expr, w_mutate_expr_args) + w_new_expr = space.call_method(w_expr, "mutate", w_visitor) space.setattr(w_self, space.wrap("expr"), w_new_expr) w_locals = space.getattr(w_self, space.wrap("locals")) if not space.is_w(w_locals, space.w_None): - w_mutate_locals = space.getattr(w_locals, space.wrap("mutate")) - w_mutate_locals_args = Arguments(space, [ w_visitor ]) - w_new_locals = space.call_args(w_mutate_locals, w_mutate_locals_args) + w_new_locals = space.call_method(w_locals, "mutate", w_visitor) space.setattr(w_self, space.wrap("locals"), w_new_locals) w_globals = space.getattr(w_self, space.wrap("globals")) if not space.is_w(w_globals, space.w_None): - w_mutate_globals = space.getattr(w_globals, space.wrap("mutate")) - w_mutate_globals_args = Arguments(space, [ w_visitor ]) - w_new_globals = space.call_args(w_mutate_globals, w_mutate_globals_args) + w_new_globals = space.call_method(w_globals, "mutate", w_visitor) space.setattr(w_self, space.wrap("globals"), w_new_globals) - w_visitExec = space.getattr(w_visitor, space.wrap("visitExec")) - w_visitExec_args = Arguments(space, [ w_self ]) - return space.call_args(w_visitExec, w_visitExec_args) + return space.call_method(w_visitor, "visitExec", w_self) Exec.typedef = TypeDef('Exec', Node.typedef, __new__ = interp2app(descr_Exec_new, unwrap_spec=[ObjSpace, W_Root, W_Root, W_Root, W_Root, int]), @@ -2463,26 +2251,18 @@ return space.wrap(self) def descr_FloorDiv_accept( space, w_self, w_visitor): - w_callable = space.getattr(w_visitor, space.wrap('visitFloorDiv')) - args = Arguments(space, [ w_self ]) - return space.call_args(w_callable, args) + return space.call_method(w_visitor, 'visitFloorDiv', w_self) def descr_FloorDiv_mutate(space, w_self, w_visitor): w_left = space.getattr(w_self, space.wrap("left")) - w_mutate_left = space.getattr(w_left, space.wrap("mutate")) - w_mutate_left_args = Arguments(space, [ w_visitor ]) - w_new_left = space.call_args(w_mutate_left, w_mutate_left_args) + w_new_left = space.call_method(w_left, "mutate", w_visitor) space.setattr(w_self, space.wrap("left"), w_new_left) w_right = space.getattr(w_self, space.wrap("right")) - w_mutate_right = space.getattr(w_right, space.wrap("mutate")) - w_mutate_right_args = Arguments(space, [ w_visitor ]) - w_new_right = space.call_args(w_mutate_right, w_mutate_right_args) + w_new_right = space.call_method(w_right, "mutate", w_visitor) space.setattr(w_self, space.wrap("right"), w_new_right) - w_visitFloorDiv = space.getattr(w_visitor, space.wrap("visitFloorDiv")) - w_visitFloorDiv_args = Arguments(space, [ w_self ]) - return space.call_args(w_visitFloorDiv, w_visitFloorDiv_args) + return space.call_method(w_visitor, "visitFloorDiv", w_self) FloorDiv.typedef = TypeDef('FloorDiv', BinaryOp.typedef, __new__ = interp2app(descr_FloorDiv_new, unwrap_spec=[ObjSpace, W_Root, W_Root, W_Root, int]), @@ -2567,39 +2347,27 @@ return space.wrap(self) def descr_For_accept( space, w_self, w_visitor): - w_callable = space.getattr(w_visitor, space.wrap('visitFor')) - args = Arguments(space, [ w_self ]) - return space.call_args(w_callable, args) + return space.call_method(w_visitor, 'visitFor', w_self) def descr_For_mutate(space, w_self, w_visitor): w_assign = space.getattr(w_self, space.wrap("assign")) - w_mutate_assign = space.getattr(w_assign, space.wrap("mutate")) - w_mutate_assign_args = Arguments(space, [ w_visitor ]) - w_new_assign = space.call_args(w_mutate_assign, w_mutate_assign_args) + w_new_assign = space.call_method(w_assign, "mutate", w_visitor) space.setattr(w_self, space.wrap("assign"), w_new_assign) w_list = space.getattr(w_self, space.wrap("list")) - w_mutate_list = space.getattr(w_list, space.wrap("mutate")) - w_mutate_list_args = Arguments(space, [ w_visitor ]) - w_new_list = space.call_args(w_mutate_list, w_mutate_list_args) + w_new_list = space.call_method(w_list, "mutate", w_visitor) space.setattr(w_self, space.wrap("list"), w_new_list) w_body = space.getattr(w_self, space.wrap("body")) - w_mutate_body = space.getattr(w_body, space.wrap("mutate")) - w_mutate_body_args = Arguments(space, [ w_visitor ]) - w_new_body = space.call_args(w_mutate_body, w_mutate_body_args) + w_new_body = space.call_method(w_body, "mutate", w_visitor) space.setattr(w_self, space.wrap("body"), w_new_body) w_else_ = space.getattr(w_self, space.wrap("else_")) if not space.is_w(w_else_, space.w_None): - w_mutate_else_ = space.getattr(w_else_, space.wrap("mutate")) - w_mutate_else__args = Arguments(space, [ w_visitor ]) - w_new_else_ = space.call_args(w_mutate_else_, w_mutate_else__args) + w_new_else_ = space.call_method(w_else_, "mutate", w_visitor) space.setattr(w_self, space.wrap("else_"), w_new_else_) - w_visitFor = space.getattr(w_visitor, space.wrap("visitFor")) - w_visitFor_args = Arguments(space, [ w_self ]) - return space.call_args(w_visitFor, w_visitFor_args) + return space.call_method(w_visitor, "visitFor", w_self) For.typedef = TypeDef('For', Node.typedef, __new__ = interp2app(descr_For_new, unwrap_spec=[ObjSpace, W_Root, W_Root, W_Root, W_Root, W_Root, int]), @@ -2676,14 +2444,10 @@ def descr_From_accept( space, w_self, w_visitor): - w_callable = space.getattr(w_visitor, space.wrap('visitFrom')) - args = Arguments(space, [ w_self ]) - return space.call_args(w_callable, args) + return space.call_method(w_visitor, 'visitFrom', w_self) def descr_From_mutate(space, w_self, w_visitor): - w_visitFrom = space.getattr(w_visitor, space.wrap("visitFrom")) - w_visitFrom_args = Arguments(space, [ w_self ]) - return space.call_args(w_visitFrom, w_visitFrom_args) + return space.call_method(w_visitor, "visitFrom", w_self) From.typedef = TypeDef('From', Node.typedef, __new__ = interp2app(descr_From_new, unwrap_spec=[ObjSpace, W_Root, W_Root, W_Root, int]), @@ -2814,25 +2578,19 @@ return space.wrap(self) def descr_Function_accept( space, w_self, w_visitor): - w_callable = space.getattr(w_visitor, space.wrap('visitFunction')) - args = Arguments(space, [ w_self ]) - return space.call_args(w_callable, args) + return space.call_method(w_visitor, 'visitFunction', w_self) def descr_Function_mutate(space, w_self, w_visitor): w_decorators = space.getattr(w_self, space.wrap("decorators")) if not space.is_w(w_decorators, space.w_None): - w_mutate_decorators = space.getattr(w_decorators, space.wrap("mutate")) - w_mutate_decorators_args = Arguments(space, [ w_visitor ]) - w_new_decorators = space.call_args(w_mutate_decorators, w_mutate_decorators_args) + w_new_decorators = space.call_method(w_decorators, "mutate", w_visitor) space.setattr(w_self, space.wrap("decorators"), w_new_decorators) w_list = space.getattr(w_self, space.wrap("argnames")) list_w = space.unpackiterable(w_list) newlist_w = [] for w_item in list_w: - w_item_mutate = space.getattr(w_item, space.wrap("mutate")) - w_item_mutate_args = Arguments(space, [ w_visitor ]) - w_newitem = space.call_args(w_item_mutate, w_item_mutate_args) + w_newitem = space.call_method(w_item, "mutate", w_visitor) if not space.is_w(w_newitem, space.w_None): newlist_w.append(w_newitem) w_newlist = space.newlist(newlist_w) @@ -2841,22 +2599,16 @@ list_w = space.unpackiterable(w_list) newlist_w = [] for w_item in list_w: - w_item_mutate = space.getattr(w_item, space.wrap("mutate")) - w_item_mutate_args = Arguments(space, [ w_visitor ]) - w_newitem = space.call_args(w_item_mutate, w_item_mutate_args) + w_newitem = space.call_method(w_item, "mutate", w_visitor) if not space.is_w(w_newitem, space.w_None): newlist_w.append(w_newitem) w_newlist = space.newlist(newlist_w) space.setattr(w_self, space.wrap("defaults"), w_newlist) w_code = space.getattr(w_self, space.wrap("code")) - w_mutate_code = space.getattr(w_code, space.wrap("mutate")) - w_mutate_code_args = Arguments(space, [ w_visitor ]) - w_new_code = space.call_args(w_mutate_code, w_mutate_code_args) + w_new_code = space.call_method(w_code, "mutate", w_visitor) space.setattr(w_self, space.wrap("code"), w_new_code) - w_visitFunction = space.getattr(w_visitor, space.wrap("visitFunction")) - w_visitFunction_args = Arguments(space, [ w_self ]) - return space.call_args(w_visitFunction, w_visitFunction_args) + return space.call_method(w_visitor, "visitFunction", w_self) Function.typedef = TypeDef('Function', AbstractFunction.typedef, __new__ = interp2app(descr_Function_new, unwrap_spec=[ObjSpace, W_Root, W_Root, W_Root, W_Root, W_Root, W_Root, W_Root, W_Root, int]), @@ -2911,20 +2663,14 @@ return space.wrap(self) def descr_GenExpr_accept( space, w_self, w_visitor): - w_callable = space.getattr(w_visitor, space.wrap('visitGenExpr')) - args = Arguments(space, [ w_self ]) - return space.call_args(w_callable, args) + return space.call_method(w_visitor, 'visitGenExpr', w_self) def descr_GenExpr_mutate(space, w_self, w_visitor): w_code = space.getattr(w_self, space.wrap("code")) - w_mutate_code = space.getattr(w_code, space.wrap("mutate")) - w_mutate_code_args = Arguments(space, [ w_visitor ]) - w_new_code = space.call_args(w_mutate_code, w_mutate_code_args) + w_new_code = space.call_method(w_code, "mutate", w_visitor) space.setattr(w_self, space.wrap("code"), w_new_code) - w_visitGenExpr = space.getattr(w_visitor, space.wrap("visitGenExpr")) - w_visitGenExpr_args = Arguments(space, [ w_self ]) - return space.call_args(w_visitGenExpr, w_visitGenExpr_args) + return space.call_method(w_visitor, "visitGenExpr", w_self) GenExpr.typedef = TypeDef('GenExpr', AbstractFunction.typedef, __new__ = interp2app(descr_GenExpr_new, unwrap_spec=[ObjSpace, W_Root, W_Root, int]), @@ -3003,37 +2749,27 @@ return space.wrap(self) def descr_GenExprFor_accept( space, w_self, w_visitor): - w_callable = space.getattr(w_visitor, space.wrap('visitGenExprFor')) - args = Arguments(space, [ w_self ]) - return space.call_args(w_callable, args) + return space.call_method(w_visitor, 'visitGenExprFor', w_self) def descr_GenExprFor_mutate(space, w_self, w_visitor): w_assign = space.getattr(w_self, space.wrap("assign")) - w_mutate_assign = space.getattr(w_assign, space.wrap("mutate")) - w_mutate_assign_args = Arguments(space, [ w_visitor ]) - w_new_assign = space.call_args(w_mutate_assign, w_mutate_assign_args) + w_new_assign = space.call_method(w_assign, "mutate", w_visitor) space.setattr(w_self, space.wrap("assign"), w_new_assign) w_iter = space.getattr(w_self, space.wrap("iter")) - w_mutate_iter = space.getattr(w_iter, space.wrap("mutate")) - w_mutate_iter_args = Arguments(space, [ w_visitor ]) - w_new_iter = space.call_args(w_mutate_iter, w_mutate_iter_args) + w_new_iter = space.call_method(w_iter, "mutate", w_visitor) space.setattr(w_self, space.wrap("iter"), w_new_iter) w_list = space.getattr(w_self, space.wrap("ifs")) list_w = space.unpackiterable(w_list) newlist_w = [] for w_item in list_w: - w_item_mutate = space.getattr(w_item, space.wrap("mutate")) - w_item_mutate_args = Arguments(space, [ w_visitor ]) - w_newitem = space.call_args(w_item_mutate, w_item_mutate_args) + w_newitem = space.call_method(w_item, "mutate", w_visitor) if not space.is_w(w_newitem, space.w_None): newlist_w.append(w_newitem) w_newlist = space.newlist(newlist_w) space.setattr(w_self, space.wrap("ifs"), w_newlist) - w_visitGenExprFor = space.getattr(w_visitor, space.wrap("visitGenExprFor")) - w_visitGenExprFor_args = Arguments(space, [ w_self ]) - return space.call_args(w_visitGenExprFor, w_visitGenExprFor_args) + return space.call_method(w_visitor, "visitGenExprFor", w_self) GenExprFor.typedef = TypeDef('GenExprFor', Node.typedef, __new__ = interp2app(descr_GenExprFor_new, unwrap_spec=[ObjSpace, W_Root, W_Root, W_Root, W_Root, int]), @@ -3080,20 +2816,14 @@ return space.wrap(self) def descr_GenExprIf_accept( space, w_self, w_visitor): - w_callable = space.getattr(w_visitor, space.wrap('visitGenExprIf')) - args = Arguments(space, [ w_self ]) - return space.call_args(w_callable, args) + return space.call_method(w_visitor, 'visitGenExprIf', w_self) def descr_GenExprIf_mutate(space, w_self, w_visitor): w_test = space.getattr(w_self, space.wrap("test")) - w_mutate_test = space.getattr(w_test, space.wrap("mutate")) - w_mutate_test_args = Arguments(space, [ w_visitor ]) - w_new_test = space.call_args(w_mutate_test, w_mutate_test_args) + w_new_test = space.call_method(w_test, "mutate", w_visitor) space.setattr(w_self, space.wrap("test"), w_new_test) - w_visitGenExprIf = space.getattr(w_visitor, space.wrap("visitGenExprIf")) - w_visitGenExprIf_args = Arguments(space, [ w_self ]) - return space.call_args(w_visitGenExprIf, w_visitGenExprIf_args) + return space.call_method(w_visitor, "visitGenExprIf", w_self) GenExprIf.typedef = TypeDef('GenExprIf', Node.typedef, __new__ = interp2app(descr_GenExprIf_new, unwrap_spec=[ObjSpace, W_Root, W_Root, int]), @@ -3159,31 +2889,23 @@ return space.wrap(self) def descr_GenExprInner_accept( space, w_self, w_visitor): - w_callable = space.getattr(w_visitor, space.wrap('visitGenExprInner')) - args = Arguments(space, [ w_self ]) - return space.call_args(w_callable, args) + return space.call_method(w_visitor, 'visitGenExprInner', w_self) def descr_GenExprInner_mutate(space, w_self, w_visitor): w_expr = space.getattr(w_self, space.wrap("expr")) - w_mutate_expr = space.getattr(w_expr, space.wrap("mutate")) - w_mutate_expr_args = Arguments(space, [ w_visitor ]) - w_new_expr = space.call_args(w_mutate_expr, w_mutate_expr_args) + w_new_expr = space.call_method(w_expr, "mutate", w_visitor) space.setattr(w_self, space.wrap("expr"), w_new_expr) w_list = space.getattr(w_self, space.wrap("quals")) list_w = space.unpackiterable(w_list) newlist_w = [] for w_item in list_w: - w_item_mutate = space.getattr(w_item, space.wrap("mutate")) - w_item_mutate_args = Arguments(space, [ w_visitor ]) - w_newitem = space.call_args(w_item_mutate, w_item_mutate_args) + w_newitem = space.call_method(w_item, "mutate", w_visitor) if not space.is_w(w_newitem, space.w_None): newlist_w.append(w_newitem) w_newlist = space.newlist(newlist_w) space.setattr(w_self, space.wrap("quals"), w_newlist) - w_visitGenExprInner = space.getattr(w_visitor, space.wrap("visitGenExprInner")) - w_visitGenExprInner_args = Arguments(space, [ w_self ]) - return space.call_args(w_visitGenExprInner, w_visitGenExprInner_args) + return space.call_method(w_visitor, "visitGenExprInner", w_self) GenExprInner.typedef = TypeDef('GenExprInner', Node.typedef, __new__ = interp2app(descr_GenExprInner_new, unwrap_spec=[ObjSpace, W_Root, W_Root, W_Root, int]), @@ -3236,20 +2958,14 @@ return space.wrap(self) def descr_Getattr_accept( space, w_self, w_visitor): - w_callable = space.getattr(w_visitor, space.wrap('visitGetattr')) - args = Arguments(space, [ w_self ]) - return space.call_args(w_callable, args) + return space.call_method(w_visitor, 'visitGetattr', w_self) def descr_Getattr_mutate(space, w_self, w_visitor): w_expr = space.getattr(w_self, space.wrap("expr")) - w_mutate_expr = space.getattr(w_expr, space.wrap("mutate")) - w_mutate_expr_args = Arguments(space, [ w_visitor ]) - w_new_expr = space.call_args(w_mutate_expr, w_mutate_expr_args) + w_new_expr = space.call_method(w_expr, "mutate", w_visitor) space.setattr(w_self, space.wrap("expr"), w_new_expr) - w_visitGetattr = space.getattr(w_visitor, space.wrap("visitGetattr")) - w_visitGetattr_args = Arguments(space, [ w_self ]) - return space.call_args(w_visitGetattr, w_visitGetattr_args) + return space.call_method(w_visitor, "visitGetattr", w_self) Getattr.typedef = TypeDef('Getattr', Node.typedef, __new__ = interp2app(descr_Getattr_new, unwrap_spec=[ObjSpace, W_Root, W_Root, W_Root, int]), @@ -3296,14 +3012,10 @@ return space.wrap(self) def descr_Global_accept( space, w_self, w_visitor): - w_callable = space.getattr(w_visitor, space.wrap('visitGlobal')) - args = Arguments(space, [ w_self ]) - return space.call_args(w_callable, args) + return space.call_method(w_visitor, 'visitGlobal', w_self) def descr_Global_mutate(space, w_self, w_visitor): - w_visitGlobal = space.getattr(w_visitor, space.wrap("visitGlobal")) - w_visitGlobal_args = Arguments(space, [ w_self ]) - return space.call_args(w_visitGlobal, w_visitGlobal_args) + return space.call_method(w_visitor, "visitGlobal", w_self) Global.typedef = TypeDef('Global', Node.typedef, __new__ = interp2app(descr_Global_new, unwrap_spec=[ObjSpace, W_Root, W_Root, int]), @@ -3392,9 +3104,7 @@ def descr_If_accept( space, w_self, w_visitor): - w_callable = space.getattr(w_visitor, space.wrap('visitIf')) - args = Arguments(space, [ w_self ]) - return space.call_args(w_callable, args) + return space.call_method(w_visitor, 'visitIf', w_self) def descr_If_mutate(space, w_self, w_visitor): w_list = space.getattr(w_self, space.wrap("tests")) @@ -3403,22 +3113,15 @@ for w_item in list_w: w_test, w_suite = space.unpackiterable(w_item, 2) - w_test_mutate = space.getattr(w_test, space.wrap("mutate")) - w_test_mutate_args = Arguments(space, [ w_visitor ]) - w_newtest = space.call_args(w_test_mutate, w_test_mutate_args) - - w_suite_mutate = space.getattr(w_suite, space.wrap("mutate")) - w_suite_mutate_args = Arguments(space, [ w_visitor ]) - w_newsuite = space.call_args(w_suite_mutate, w_suite_mutate_args) + w_newtest = space.call_method(w_test, "mutate", w_visitor) + w_newsuite = space.call_method(w_suite, "mutate", w_visitor) newlist_w.append(space.newtuple([w_newtest, w_newsuite])) w_newlist = space.newlist(newlist_w) space.setattr(w_self, space.wrap("tests"), w_newlist) w_else_ = space.getattr(w_self, space.wrap("else_")) if not space.is_w(w_else_, space.w_None): - w_mutate_else_ = space.getattr(w_else_, space.wrap("mutate")) - w_mutate_else__args = Arguments(space, [ w_visitor ]) - w_new_else_ = space.call_args(w_mutate_else_, w_mutate_else__args) + w_new_else_ = space.call_method(w_else_, "mutate", w_visitor) space.setattr(w_self, space.wrap("else_"), w_new_else_) @@ -3490,14 +3193,10 @@ def descr_Import_accept( space, w_self, w_visitor): - w_callable = space.getattr(w_visitor, space.wrap('visitImport')) - args = Arguments(space, [ w_self ]) - return space.call_args(w_callable, args) + return space.call_method(w_visitor, 'visitImport', w_self) def descr_Import_mutate(space, w_self, w_visitor): - w_visitImport = space.getattr(w_visitor, space.wrap("visitImport")) - w_visitImport_args = Arguments(space, [ w_self ]) - return space.call_args(w_visitImport, w_visitImport_args) + return space.call_method(w_visitor, "visitImport", w_self) Import.typedef = TypeDef('Import', Node.typedef, __new__ = interp2app(descr_Import_new, unwrap_spec=[ObjSpace, W_Root, W_Root, int]), @@ -3542,20 +3241,14 @@ return space.wrap(self) def descr_Invert_accept( space, w_self, w_visitor): - w_callable = space.getattr(w_visitor, space.wrap('visitInvert')) - args = Arguments(space, [ w_self ]) - return space.call_args(w_callable, args) + return space.call_method(w_visitor, 'visitInvert', w_self) def descr_Invert_mutate(space, w_self, w_visitor): w_expr = space.getattr(w_self, space.wrap("expr")) - w_mutate_expr = space.getattr(w_expr, space.wrap("mutate")) - w_mutate_expr_args = Arguments(space, [ w_visitor ]) - w_new_expr = space.call_args(w_mutate_expr, w_mutate_expr_args) + w_new_expr = space.call_method(w_expr, "mutate", w_visitor) space.setattr(w_self, space.wrap("expr"), w_new_expr) - w_visitInvert = space.getattr(w_visitor, space.wrap("visitInvert")) - w_visitInvert_args = Arguments(space, [ w_self ]) - return space.call_args(w_visitInvert, w_visitInvert_args) + return space.call_method(w_visitor, "visitInvert", w_self) Invert.typedef = TypeDef('Invert', UnaryOp.typedef, __new__ = interp2app(descr_Invert_new, unwrap_spec=[ObjSpace, W_Root, W_Root, int]), @@ -3607,20 +3300,14 @@ return space.wrap(self) def descr_Keyword_accept( space, w_self, w_visitor): - w_callable = space.getattr(w_visitor, space.wrap('visitKeyword')) - args = Arguments(space, [ w_self ]) - return space.call_args(w_callable, args) + return space.call_method(w_visitor, 'visitKeyword', w_self) def descr_Keyword_mutate(space, w_self, w_visitor): w_expr = space.getattr(w_self, space.wrap("expr")) - w_mutate_expr = space.getattr(w_expr, space.wrap("mutate")) - w_mutate_expr_args = Arguments(space, [ w_visitor ]) - w_new_expr = space.call_args(w_mutate_expr, w_mutate_expr_args) + w_new_expr = space.call_method(w_expr, "mutate", w_visitor) space.setattr(w_self, space.wrap("expr"), w_new_expr) - w_visitKeyword = space.getattr(w_visitor, space.wrap("visitKeyword")) - w_visitKeyword_args = Arguments(space, [ w_self ]) - return space.call_args(w_visitKeyword, w_visitKeyword_args) + return space.call_method(w_visitor, "visitKeyword", w_self) Keyword.typedef = TypeDef('Keyword', Node.typedef, __new__ = interp2app(descr_Keyword_new, unwrap_spec=[ObjSpace, W_Root, W_Root, W_Root, int]), @@ -3719,18 +3406,14 @@ return space.wrap(self) def descr_Lambda_accept( space, w_self, w_visitor): - w_callable = space.getattr(w_visitor, space.wrap('visitLambda')) - args = Arguments(space, [ w_self ]) - return space.call_args(w_callable, args) + return space.call_method(w_visitor, 'visitLambda', w_self) def descr_Lambda_mutate(space, w_self, w_visitor): w_list = space.getattr(w_self, space.wrap("argnames")) list_w = space.unpackiterable(w_list) newlist_w = [] for w_item in list_w: - w_item_mutate = space.getattr(w_item, space.wrap("mutate")) - w_item_mutate_args = Arguments(space, [ w_visitor ]) - w_newitem = space.call_args(w_item_mutate, w_item_mutate_args) + w_newitem = space.call_method(w_item, "mutate", w_visitor) if not space.is_w(w_newitem, space.w_None): newlist_w.append(w_newitem) w_newlist = space.newlist(newlist_w) @@ -3739,22 +3422,16 @@ list_w = space.unpackiterable(w_list) newlist_w = [] for w_item in list_w: - w_item_mutate = space.getattr(w_item, space.wrap("mutate")) - w_item_mutate_args = Arguments(space, [ w_visitor ]) - w_newitem = space.call_args(w_item_mutate, w_item_mutate_args) + w_newitem = space.call_method(w_item, "mutate", w_visitor) if not space.is_w(w_newitem, space.w_None): newlist_w.append(w_newitem) w_newlist = space.newlist(newlist_w) space.setattr(w_self, space.wrap("defaults"), w_newlist) w_code = space.getattr(w_self, space.wrap("code")) - w_mutate_code = space.getattr(w_code, space.wrap("mutate")) - w_mutate_code_args = Arguments(space, [ w_visitor ]) - w_new_code = space.call_args(w_mutate_code, w_mutate_code_args) + w_new_code = space.call_method(w_code, "mutate", w_visitor) space.setattr(w_self, space.wrap("code"), w_new_code) - w_visitLambda = space.getattr(w_visitor, space.wrap("visitLambda")) - w_visitLambda_args = Arguments(space, [ w_self ]) - return space.call_args(w_visitLambda, w_visitLambda_args) + return space.call_method(w_visitor, "visitLambda", w_self) Lambda.typedef = TypeDef('Lambda', AbstractFunction.typedef, __new__ = interp2app(descr_Lambda_new, unwrap_spec=[ObjSpace, W_Root, W_Root, W_Root, W_Root, W_Root, int]), @@ -3810,26 +3487,18 @@ return space.wrap(self) def descr_LeftShift_accept( space, w_self, w_visitor): - w_callable = space.getattr(w_visitor, space.wrap('visitLeftShift')) - args = Arguments(space, [ w_self ]) - return space.call_args(w_callable, args) + return space.call_method(w_visitor, 'visitLeftShift', w_self) def descr_LeftShift_mutate(space, w_self, w_visitor): w_left = space.getattr(w_self, space.wrap("left")) - w_mutate_left = space.getattr(w_left, space.wrap("mutate")) - w_mutate_left_args = Arguments(space, [ w_visitor ]) - w_new_left = space.call_args(w_mutate_left, w_mutate_left_args) + w_new_left = space.call_method(w_left, "mutate", w_visitor) space.setattr(w_self, space.wrap("left"), w_new_left) w_right = space.getattr(w_self, space.wrap("right")) - w_mutate_right = space.getattr(w_right, space.wrap("mutate")) - w_mutate_right_args = Arguments(space, [ w_visitor ]) - w_new_right = space.call_args(w_mutate_right, w_mutate_right_args) + w_new_right = space.call_method(w_right, "mutate", w_visitor) space.setattr(w_self, space.wrap("right"), w_new_right) - w_visitLeftShift = space.getattr(w_visitor, space.wrap("visitLeftShift")) - w_visitLeftShift_args = Arguments(space, [ w_self ]) - return space.call_args(w_visitLeftShift, w_visitLeftShift_args) + return space.call_method(w_visitor, "visitLeftShift", w_self) LeftShift.typedef = TypeDef('LeftShift', BinaryOp.typedef, __new__ = interp2app(descr_LeftShift_new, unwrap_spec=[ObjSpace, W_Root, W_Root, W_Root, int]), @@ -3884,25 +3553,19 @@ return space.wrap(self) def descr_List_accept( space, w_self, w_visitor): - w_callable = space.getattr(w_visitor, space.wrap('visitList')) - args = Arguments(space, [ w_self ]) - return space.call_args(w_callable, args) + return space.call_method(w_visitor, 'visitList', w_self) def descr_List_mutate(space, w_self, w_visitor): w_list = space.getattr(w_self, space.wrap("nodes")) list_w = space.unpackiterable(w_list) newlist_w = [] for w_item in list_w: - w_item_mutate = space.getattr(w_item, space.wrap("mutate")) - w_item_mutate_args = Arguments(space, [ w_visitor ]) - w_newitem = space.call_args(w_item_mutate, w_item_mutate_args) + w_newitem = space.call_method(w_item, "mutate", w_visitor) if not space.is_w(w_newitem, space.w_None): newlist_w.append(w_newitem) w_newlist = space.newlist(newlist_w) space.setattr(w_self, space.wrap("nodes"), w_newlist) - w_visitList = space.getattr(w_visitor, space.wrap("visitList")) - w_visitList_args = Arguments(space, [ w_self ]) - return space.call_args(w_visitList, w_visitList_args) + return space.call_method(w_visitor, "visitList", w_self) List.typedef = TypeDef('List', Node.typedef, __new__ = interp2app(descr_List_new, unwrap_spec=[ObjSpace, W_Root, W_Root, int]), @@ -3968,31 +3631,23 @@ return space.wrap(self) def descr_ListComp_accept( space, w_self, w_visitor): - w_callable = space.getattr(w_visitor, space.wrap('visitListComp')) - args = Arguments(space, [ w_self ]) - return space.call_args(w_callable, args) + return space.call_method(w_visitor, 'visitListComp', w_self) def descr_ListComp_mutate(space, w_self, w_visitor): w_expr = space.getattr(w_self, space.wrap("expr")) - w_mutate_expr = space.getattr(w_expr, space.wrap("mutate")) - w_mutate_expr_args = Arguments(space, [ w_visitor ]) - w_new_expr = space.call_args(w_mutate_expr, w_mutate_expr_args) + w_new_expr = space.call_method(w_expr, "mutate", w_visitor) space.setattr(w_self, space.wrap("expr"), w_new_expr) w_list = space.getattr(w_self, space.wrap("quals")) list_w = space.unpackiterable(w_list) newlist_w = [] for w_item in list_w: - w_item_mutate = space.getattr(w_item, space.wrap("mutate")) - w_item_mutate_args = Arguments(space, [ w_visitor ]) - w_newitem = space.call_args(w_item_mutate, w_item_mutate_args) + w_newitem = space.call_method(w_item, "mutate", w_visitor) if not space.is_w(w_newitem, space.w_None): newlist_w.append(w_newitem) w_newlist = space.newlist(newlist_w) space.setattr(w_self, space.wrap("quals"), w_newlist) - w_visitListComp = space.getattr(w_visitor, space.wrap("visitListComp")) - w_visitListComp_args = Arguments(space, [ w_self ]) - return space.call_args(w_visitListComp, w_visitListComp_args) + return space.call_method(w_visitor, "visitListComp", w_self) ListComp.typedef = TypeDef('ListComp', Node.typedef, __new__ = interp2app(descr_ListComp_new, unwrap_spec=[ObjSpace, W_Root, W_Root, W_Root, int]), @@ -4069,37 +3724,27 @@ return space.wrap(self) def descr_ListCompFor_accept( space, w_self, w_visitor): - w_callable = space.getattr(w_visitor, space.wrap('visitListCompFor')) - args = Arguments(space, [ w_self ]) - return space.call_args(w_callable, args) + return space.call_method(w_visitor, 'visitListCompFor', w_self) def descr_ListCompFor_mutate(space, w_self, w_visitor): w_assign = space.getattr(w_self, space.wrap("assign")) - w_mutate_assign = space.getattr(w_assign, space.wrap("mutate")) - w_mutate_assign_args = Arguments(space, [ w_visitor ]) - w_new_assign = space.call_args(w_mutate_assign, w_mutate_assign_args) + w_new_assign = space.call_method(w_assign, "mutate", w_visitor) space.setattr(w_self, space.wrap("assign"), w_new_assign) w_list = space.getattr(w_self, space.wrap("list")) - w_mutate_list = space.getattr(w_list, space.wrap("mutate")) - w_mutate_list_args = Arguments(space, [ w_visitor ]) - w_new_list = space.call_args(w_mutate_list, w_mutate_list_args) + w_new_list = space.call_method(w_list, "mutate", w_visitor) space.setattr(w_self, space.wrap("list"), w_new_list) w_list = space.getattr(w_self, space.wrap("ifs")) list_w = space.unpackiterable(w_list) newlist_w = [] for w_item in list_w: - w_item_mutate = space.getattr(w_item, space.wrap("mutate")) - w_item_mutate_args = Arguments(space, [ w_visitor ]) - w_newitem = space.call_args(w_item_mutate, w_item_mutate_args) + w_newitem = space.call_method(w_item, "mutate", w_visitor) if not space.is_w(w_newitem, space.w_None): newlist_w.append(w_newitem) w_newlist = space.newlist(newlist_w) space.setattr(w_self, space.wrap("ifs"), w_newlist) - w_visitListCompFor = space.getattr(w_visitor, space.wrap("visitListCompFor")) - w_visitListCompFor_args = Arguments(space, [ w_self ]) - return space.call_args(w_visitListCompFor, w_visitListCompFor_args) + return space.call_method(w_visitor, "visitListCompFor", w_self) ListCompFor.typedef = TypeDef('ListCompFor', Node.typedef, __new__ = interp2app(descr_ListCompFor_new, unwrap_spec=[ObjSpace, W_Root, W_Root, W_Root, W_Root, int]), @@ -4146,20 +3791,14 @@ return space.wrap(self) def descr_ListCompIf_accept( space, w_self, w_visitor): - w_callable = space.getattr(w_visitor, space.wrap('visitListCompIf')) - args = Arguments(space, [ w_self ]) - return space.call_args(w_callable, args) + return space.call_method(w_visitor, 'visitListCompIf', w_self) def descr_ListCompIf_mutate(space, w_self, w_visitor): w_test = space.getattr(w_self, space.wrap("test")) - w_mutate_test = space.getattr(w_test, space.wrap("mutate")) - w_mutate_test_args = Arguments(space, [ w_visitor ]) - w_new_test = space.call_args(w_mutate_test, w_mutate_test_args) + w_new_test = space.call_method(w_test, "mutate", w_visitor) space.setattr(w_self, space.wrap("test"), w_new_test) - w_visitListCompIf = space.getattr(w_visitor, space.wrap("visitListCompIf")) - w_visitListCompIf_args = Arguments(space, [ w_self ]) - return space.call_args(w_visitListCompIf, w_visitListCompIf_args) + return space.call_method(w_visitor, "visitListCompIf", w_self) ListCompIf.typedef = TypeDef('ListCompIf', Node.typedef, __new__ = interp2app(descr_ListCompIf_new, unwrap_spec=[ObjSpace, W_Root, W_Root, int]), @@ -4212,26 +3851,18 @@ return space.wrap(self) def descr_Mod_accept( space, w_self, w_visitor): - w_callable = space.getattr(w_visitor, space.wrap('visitMod')) - args = Arguments(space, [ w_self ]) - return space.call_args(w_callable, args) + return space.call_method(w_visitor, 'visitMod', w_self) def descr_Mod_mutate(space, w_self, w_visitor): w_left = space.getattr(w_self, space.wrap("left")) - w_mutate_left = space.getattr(w_left, space.wrap("mutate")) - w_mutate_left_args = Arguments(space, [ w_visitor ]) - w_new_left = space.call_args(w_mutate_left, w_mutate_left_args) + w_new_left = space.call_method(w_left, "mutate", w_visitor) space.setattr(w_self, space.wrap("left"), w_new_left) w_right = space.getattr(w_self, space.wrap("right")) - w_mutate_right = space.getattr(w_right, space.wrap("mutate")) - w_mutate_right_args = Arguments(space, [ w_visitor ]) - w_new_right = space.call_args(w_mutate_right, w_mutate_right_args) + w_new_right = space.call_method(w_right, "mutate", w_visitor) space.setattr(w_self, space.wrap("right"), w_new_right) - w_visitMod = space.getattr(w_visitor, space.wrap("visitMod")) - w_visitMod_args = Arguments(space, [ w_self ]) - return space.call_args(w_visitMod, w_visitMod_args) + return space.call_method(w_visitor, "visitMod", w_self) Mod.typedef = TypeDef('Mod', BinaryOp.typedef, __new__ = interp2app(descr_Mod_new, unwrap_spec=[ObjSpace, W_Root, W_Root, W_Root, int]), @@ -4285,20 +3916,14 @@ return space.wrap(self) def descr_Module_accept( space, w_self, w_visitor): - w_callable = space.getattr(w_visitor, space.wrap('visitModule')) - args = Arguments(space, [ w_self ]) - return space.call_args(w_callable, args) + return space.call_method(w_visitor, 'visitModule', w_self) def descr_Module_mutate(space, w_self, w_visitor): w_node = space.getattr(w_self, space.wrap("node")) - w_mutate_node = space.getattr(w_node, space.wrap("mutate")) - w_mutate_node_args = Arguments(space, [ w_visitor ]) - w_new_node = space.call_args(w_mutate_node, w_mutate_node_args) + w_new_node = space.call_method(w_node, "mutate", w_visitor) space.setattr(w_self, space.wrap("node"), w_new_node) - w_visitModule = space.getattr(w_visitor, space.wrap("visitModule")) - w_visitModule_args = Arguments(space, [ w_self ]) - return space.call_args(w_visitModule, w_visitModule_args) + return space.call_method(w_visitor, "visitModule", w_self) Module.typedef = TypeDef('Module', Node.typedef, __new__ = interp2app(descr_Module_new, unwrap_spec=[ObjSpace, W_Root, W_Root, W_Root, int]), @@ -4352,26 +3977,18 @@ return space.wrap(self) def descr_Mul_accept( space, w_self, w_visitor): - w_callable = space.getattr(w_visitor, space.wrap('visitMul')) - args = Arguments(space, [ w_self ]) - return space.call_args(w_callable, args) + return space.call_method(w_visitor, 'visitMul', w_self) def descr_Mul_mutate(space, w_self, w_visitor): w_left = space.getattr(w_self, space.wrap("left")) - w_mutate_left = space.getattr(w_left, space.wrap("mutate")) - w_mutate_left_args = Arguments(space, [ w_visitor ]) - w_new_left = space.call_args(w_mutate_left, w_mutate_left_args) + w_new_left = space.call_method(w_left, "mutate", w_visitor) space.setattr(w_self, space.wrap("left"), w_new_left) w_right = space.getattr(w_self, space.wrap("right")) - w_mutate_right = space.getattr(w_right, space.wrap("mutate")) - w_mutate_right_args = Arguments(space, [ w_visitor ]) - w_new_right = space.call_args(w_mutate_right, w_mutate_right_args) + w_new_right = space.call_method(w_right, "mutate", w_visitor) space.setattr(w_self, space.wrap("right"), w_new_right) - w_visitMul = space.getattr(w_visitor, space.wrap("visitMul")) - w_visitMul_args = Arguments(space, [ w_self ]) - return space.call_args(w_visitMul, w_visitMul_args) + return space.call_method(w_visitor, "visitMul", w_self) Mul.typedef = TypeDef('Mul', BinaryOp.typedef, __new__ = interp2app(descr_Mul_new, unwrap_spec=[ObjSpace, W_Root, W_Root, W_Root, int]), @@ -4416,14 +4033,10 @@ return space.wrap(self) def descr_Name_accept( space, w_self, w_visitor): - w_callable = space.getattr(w_visitor, space.wrap('visitName')) - args = Arguments(space, [ w_self ]) - return space.call_args(w_callable, args) + return space.call_method(w_visitor, 'visitName', w_self) def descr_Name_mutate(space, w_self, w_visitor): - w_visitName = space.getattr(w_visitor, space.wrap("visitName")) - w_visitName_args = Arguments(space, [ w_self ]) - return space.call_args(w_visitName, w_visitName_args) + return space.call_method(w_visitor, "visitName", w_self) Name.typedef = TypeDef('Name', Node.typedef, __new__ = interp2app(descr_Name_new, unwrap_spec=[ObjSpace, W_Root, W_Root, int]), @@ -4460,14 +4073,10 @@ return space.wrap(self) def descr_NoneConst_accept( space, w_self, w_visitor): - w_callable = space.getattr(w_visitor, space.wrap('visitNoneConst')) - args = Arguments(space, [ w_self ]) - return space.call_args(w_callable, args) + return space.call_method(w_visitor, 'visitNoneConst', w_self) def descr_NoneConst_mutate(space, w_self, w_visitor): - w_visitNoneConst = space.getattr(w_visitor, space.wrap("visitNoneConst")) - w_visitNoneConst_args = Arguments(space, [ w_self ]) - return space.call_args(w_visitNoneConst, w_visitNoneConst_args) + return space.call_method(w_visitor, "visitNoneConst", w_self) NoneConst.typedef = TypeDef('NoneConst', Node.typedef, __new__ = interp2app(descr_NoneConst_new, unwrap_spec=[ObjSpace, W_Root, int]), @@ -4511,20 +4120,14 @@ return space.wrap(self) def descr_Not_accept( space, w_self, w_visitor): - w_callable = space.getattr(w_visitor, space.wrap('visitNot')) - args = Arguments(space, [ w_self ]) - return space.call_args(w_callable, args) + return space.call_method(w_visitor, 'visitNot', w_self) def descr_Not_mutate(space, w_self, w_visitor): w_expr = space.getattr(w_self, space.wrap("expr")) - w_mutate_expr = space.getattr(w_expr, space.wrap("mutate")) - w_mutate_expr_args = Arguments(space, [ w_visitor ]) - w_new_expr = space.call_args(w_mutate_expr, w_mutate_expr_args) + w_new_expr = space.call_method(w_expr, "mutate", w_visitor) space.setattr(w_self, space.wrap("expr"), w_new_expr) - w_visitNot = space.getattr(w_visitor, space.wrap("visitNot")) - w_visitNot_args = Arguments(space, [ w_self ]) - return space.call_args(w_visitNot, w_visitNot_args) + return space.call_method(w_visitor, "visitNot", w_self) Not.typedef = TypeDef('Not', UnaryOp.typedef, __new__ = interp2app(descr_Not_new, unwrap_spec=[ObjSpace, W_Root, W_Root, int]), @@ -4578,25 +4181,19 @@ return space.wrap(self) def descr_Or_accept( space, w_self, w_visitor): - w_callable = space.getattr(w_visitor, space.wrap('visitOr')) - args = Arguments(space, [ w_self ]) - return space.call_args(w_callable, args) + return space.call_method(w_visitor, 'visitOr', w_self) def descr_Or_mutate(space, w_self, w_visitor): w_list = space.getattr(w_self, space.wrap("nodes")) list_w = space.unpackiterable(w_list) newlist_w = [] for w_item in list_w: - w_item_mutate = space.getattr(w_item, space.wrap("mutate")) - w_item_mutate_args = Arguments(space, [ w_visitor ]) - w_newitem = space.call_args(w_item_mutate, w_item_mutate_args) + w_newitem = space.call_method(w_item, "mutate", w_visitor) if not space.is_w(w_newitem, space.w_None): newlist_w.append(w_newitem) w_newlist = space.newlist(newlist_w) space.setattr(w_self, space.wrap("nodes"), w_newlist) - w_visitOr = space.getattr(w_visitor, space.wrap("visitOr")) - w_visitOr_args = Arguments(space, [ w_self ]) - return space.call_args(w_visitOr, w_visitOr_args) + return space.call_method(w_visitor, "visitOr", w_self) Or.typedef = TypeDef('Or', AbstractTest.typedef, __new__ = interp2app(descr_Or_new, unwrap_spec=[ObjSpace, W_Root, W_Root, int]), @@ -4633,14 +4230,10 @@ return space.wrap(self) def descr_Pass_accept( space, w_self, w_visitor): - w_callable = space.getattr(w_visitor, space.wrap('visitPass')) - args = Arguments(space, [ w_self ]) - return space.call_args(w_callable, args) + return space.call_method(w_visitor, 'visitPass', w_self) def descr_Pass_mutate(space, w_self, w_visitor): - w_visitPass = space.getattr(w_visitor, space.wrap("visitPass")) - w_visitPass_args = Arguments(space, [ w_self ]) - return space.call_args(w_visitPass, w_visitPass_args) + return space.call_method(w_visitor, "visitPass", w_self) Pass.typedef = TypeDef('Pass', Node.typedef, __new__ = interp2app(descr_Pass_new, unwrap_spec=[ObjSpace, W_Root, int]), @@ -4692,26 +4285,18 @@ return space.wrap(self) def descr_Power_accept( space, w_self, w_visitor): - w_callable = space.getattr(w_visitor, space.wrap('visitPower')) - args = Arguments(space, [ w_self ]) - return space.call_args(w_callable, args) + return space.call_method(w_visitor, 'visitPower', w_self) def descr_Power_mutate(space, w_self, w_visitor): w_left = space.getattr(w_self, space.wrap("left")) - w_mutate_left = space.getattr(w_left, space.wrap("mutate")) - w_mutate_left_args = Arguments(space, [ w_visitor ]) - w_new_left = space.call_args(w_mutate_left, w_mutate_left_args) + w_new_left = space.call_method(w_left, "mutate", w_visitor) space.setattr(w_self, space.wrap("left"), w_new_left) w_right = space.getattr(w_self, space.wrap("right")) - w_mutate_right = space.getattr(w_right, space.wrap("mutate")) - w_mutate_right_args = Arguments(space, [ w_visitor ]) - w_new_right = space.call_args(w_mutate_right, w_mutate_right_args) + w_new_right = space.call_method(w_right, "mutate", w_visitor) space.setattr(w_self, space.wrap("right"), w_new_right) - w_visitPower = space.getattr(w_visitor, space.wrap("visitPower")) - w_visitPower_args = Arguments(space, [ w_self ]) - return space.call_args(w_visitPower, w_visitPower_args) + return space.call_method(w_visitor, "visitPower", w_self) Power.typedef = TypeDef('Power', BinaryOp.typedef, __new__ = interp2app(descr_Power_new, unwrap_spec=[ObjSpace, W_Root, W_Root, W_Root, int]), @@ -4783,32 +4368,24 @@ return space.wrap(self) def descr_Print_accept( space, w_self, w_visitor): - w_callable = space.getattr(w_visitor, space.wrap('visitPrint')) - args = Arguments(space, [ w_self ]) - return space.call_args(w_callable, args) + return space.call_method(w_visitor, 'visitPrint', w_self) def descr_Print_mutate(space, w_self, w_visitor): w_list = space.getattr(w_self, space.wrap("nodes")) list_w = space.unpackiterable(w_list) newlist_w = [] for w_item in list_w: - w_item_mutate = space.getattr(w_item, space.wrap("mutate")) - w_item_mutate_args = Arguments(space, [ w_visitor ]) - w_newitem = space.call_args(w_item_mutate, w_item_mutate_args) + w_newitem = space.call_method(w_item, "mutate", w_visitor) if not space.is_w(w_newitem, space.w_None): newlist_w.append(w_newitem) w_newlist = space.newlist(newlist_w) space.setattr(w_self, space.wrap("nodes"), w_newlist) w_dest = space.getattr(w_self, space.wrap("dest")) if not space.is_w(w_dest, space.w_None): - w_mutate_dest = space.getattr(w_dest, space.wrap("mutate")) - w_mutate_dest_args = Arguments(space, [ w_visitor ]) - w_new_dest = space.call_args(w_mutate_dest, w_mutate_dest_args) + w_new_dest = space.call_method(w_dest, "mutate", w_visitor) space.setattr(w_self, space.wrap("dest"), w_new_dest) - w_visitPrint = space.getattr(w_visitor, space.wrap("visitPrint")) - w_visitPrint_args = Arguments(space, [ w_self ]) - return space.call_args(w_visitPrint, w_visitPrint_args) + return space.call_method(w_visitor, "visitPrint", w_self) Print.typedef = TypeDef('Print', Node.typedef, __new__ = interp2app(descr_Print_new, unwrap_spec=[ObjSpace, W_Root, W_Root, W_Root, int]), @@ -4880,32 +4457,24 @@ return space.wrap(self) def descr_Printnl_accept( space, w_self, w_visitor): - w_callable = space.getattr(w_visitor, space.wrap('visitPrintnl')) - args = Arguments(space, [ w_self ]) - return space.call_args(w_callable, args) + return space.call_method(w_visitor, 'visitPrintnl', w_self) def descr_Printnl_mutate(space, w_self, w_visitor): w_list = space.getattr(w_self, space.wrap("nodes")) list_w = space.unpackiterable(w_list) newlist_w = [] for w_item in list_w: - w_item_mutate = space.getattr(w_item, space.wrap("mutate")) - w_item_mutate_args = Arguments(space, [ w_visitor ]) - w_newitem = space.call_args(w_item_mutate, w_item_mutate_args) + w_newitem = space.call_method(w_item, "mutate", w_visitor) if not space.is_w(w_newitem, space.w_None): newlist_w.append(w_newitem) w_newlist = space.newlist(newlist_w) space.setattr(w_self, space.wrap("nodes"), w_newlist) w_dest = space.getattr(w_self, space.wrap("dest")) if not space.is_w(w_dest, space.w_None): - w_mutate_dest = space.getattr(w_dest, space.wrap("mutate")) - w_mutate_dest_args = Arguments(space, [ w_visitor ]) - w_new_dest = space.call_args(w_mutate_dest, w_mutate_dest_args) + w_new_dest = space.call_method(w_dest, "mutate", w_visitor) space.setattr(w_self, space.wrap("dest"), w_new_dest) - w_visitPrintnl = space.getattr(w_visitor, space.wrap("visitPrintnl")) - w_visitPrintnl_args = Arguments(space, [ w_self ]) - return space.call_args(w_visitPrintnl, w_visitPrintnl_args) + return space.call_method(w_visitor, "visitPrintnl", w_self) Printnl.typedef = TypeDef('Printnl', Node.typedef, __new__ = interp2app(descr_Printnl_new, unwrap_spec=[ObjSpace, W_Root, W_Root, W_Root, int]), @@ -4990,35 +4559,25 @@ return space.wrap(self) def descr_Raise_accept( space, w_self, w_visitor): - w_callable = space.getattr(w_visitor, space.wrap('visitRaise')) - args = Arguments(space, [ w_self ]) - return space.call_args(w_callable, args) + return space.call_method(w_visitor, 'visitRaise', w_self) def descr_Raise_mutate(space, w_self, w_visitor): w_expr1 = space.getattr(w_self, space.wrap("expr1")) if not space.is_w(w_expr1, space.w_None): - w_mutate_expr1 = space.getattr(w_expr1, space.wrap("mutate")) - w_mutate_expr1_args = Arguments(space, [ w_visitor ]) - w_new_expr1 = space.call_args(w_mutate_expr1, w_mutate_expr1_args) + w_new_expr1 = space.call_method(w_expr1, "mutate", w_visitor) space.setattr(w_self, space.wrap("expr1"), w_new_expr1) w_expr2 = space.getattr(w_self, space.wrap("expr2")) if not space.is_w(w_expr2, space.w_None): - w_mutate_expr2 = space.getattr(w_expr2, space.wrap("mutate")) - w_mutate_expr2_args = Arguments(space, [ w_visitor ]) - w_new_expr2 = space.call_args(w_mutate_expr2, w_mutate_expr2_args) + w_new_expr2 = space.call_method(w_expr2, "mutate", w_visitor) space.setattr(w_self, space.wrap("expr2"), w_new_expr2) w_expr3 = space.getattr(w_self, space.wrap("expr3")) if not space.is_w(w_expr3, space.w_None): - w_mutate_expr3 = space.getattr(w_expr3, space.wrap("mutate")) - w_mutate_expr3_args = Arguments(space, [ w_visitor ]) - w_new_expr3 = space.call_args(w_mutate_expr3, w_mutate_expr3_args) + w_new_expr3 = space.call_method(w_expr3, "mutate", w_visitor) space.setattr(w_self, space.wrap("expr3"), w_new_expr3) - w_visitRaise = space.getattr(w_visitor, space.wrap("visitRaise")) - w_visitRaise_args = Arguments(space, [ w_self ]) - return space.call_args(w_visitRaise, w_visitRaise_args) + return space.call_method(w_visitor, "visitRaise", w_self) Raise.typedef = TypeDef('Raise', Node.typedef, __new__ = interp2app(descr_Raise_new, unwrap_spec=[ObjSpace, W_Root, W_Root, W_Root, W_Root, int]), @@ -5072,21 +4631,15 @@ return space.wrap(self) def descr_Return_accept( space, w_self, w_visitor): - w_callable = space.getattr(w_visitor, space.wrap('visitReturn')) - args = Arguments(space, [ w_self ]) - return space.call_args(w_callable, args) + return space.call_method(w_visitor, 'visitReturn', w_self) def descr_Return_mutate(space, w_self, w_visitor): w_value = space.getattr(w_self, space.wrap("value")) if not space.is_w(w_value, space.w_None): - w_mutate_value = space.getattr(w_value, space.wrap("mutate")) - w_mutate_value_args = Arguments(space, [ w_visitor ]) - w_new_value = space.call_args(w_mutate_value, w_mutate_value_args) + w_new_value = space.call_method(w_value, "mutate", w_visitor) space.setattr(w_self, space.wrap("value"), w_new_value) - w_visitReturn = space.getattr(w_visitor, space.wrap("visitReturn")) - w_visitReturn_args = Arguments(space, [ w_self ]) - return space.call_args(w_visitReturn, w_visitReturn_args) + return space.call_method(w_visitor, "visitReturn", w_self) Return.typedef = TypeDef('Return', Node.typedef, __new__ = interp2app(descr_Return_new, unwrap_spec=[ObjSpace, W_Root, W_Root, int]), @@ -5139,26 +4692,18 @@ return space.wrap(self) def descr_RightShift_accept( space, w_self, w_visitor): - w_callable = space.getattr(w_visitor, space.wrap('visitRightShift')) - args = Arguments(space, [ w_self ]) - return space.call_args(w_callable, args) + return space.call_method(w_visitor, 'visitRightShift', w_self) def descr_RightShift_mutate(space, w_self, w_visitor): w_left = space.getattr(w_self, space.wrap("left")) - w_mutate_left = space.getattr(w_left, space.wrap("mutate")) - w_mutate_left_args = Arguments(space, [ w_visitor ]) - w_new_left = space.call_args(w_mutate_left, w_mutate_left_args) + w_new_left = space.call_method(w_left, "mutate", w_visitor) space.setattr(w_self, space.wrap("left"), w_new_left) w_right = space.getattr(w_self, space.wrap("right")) - w_mutate_right = space.getattr(w_right, space.wrap("mutate")) - w_mutate_right_args = Arguments(space, [ w_visitor ]) - w_new_right = space.call_args(w_mutate_right, w_mutate_right_args) + w_new_right = space.call_method(w_right, "mutate", w_visitor) space.setattr(w_self, space.wrap("right"), w_new_right) - w_visitRightShift = space.getattr(w_visitor, space.wrap("visitRightShift")) - w_visitRightShift_args = Arguments(space, [ w_self ]) - return space.call_args(w_visitRightShift, w_visitRightShift_args) + return space.call_method(w_visitor, "visitRightShift", w_self) RightShift.typedef = TypeDef('RightShift', BinaryOp.typedef, __new__ = interp2app(descr_RightShift_new, unwrap_spec=[ObjSpace, W_Root, W_Root, W_Root, int]), @@ -5246,34 +4791,24 @@ return space.wrap(self) def descr_Slice_accept( space, w_self, w_visitor): - w_callable = space.getattr(w_visitor, space.wrap('visitSlice')) - args = Arguments(space, [ w_self ]) - return space.call_args(w_callable, args) + return space.call_method(w_visitor, 'visitSlice', w_self) def descr_Slice_mutate(space, w_self, w_visitor): w_expr = space.getattr(w_self, space.wrap("expr")) - w_mutate_expr = space.getattr(w_expr, space.wrap("mutate")) - w_mutate_expr_args = Arguments(space, [ w_visitor ]) - w_new_expr = space.call_args(w_mutate_expr, w_mutate_expr_args) + w_new_expr = space.call_method(w_expr, "mutate", w_visitor) space.setattr(w_self, space.wrap("expr"), w_new_expr) w_lower = space.getattr(w_self, space.wrap("lower")) if not space.is_w(w_lower, space.w_None): - w_mutate_lower = space.getattr(w_lower, space.wrap("mutate")) - w_mutate_lower_args = Arguments(space, [ w_visitor ]) - w_new_lower = space.call_args(w_mutate_lower, w_mutate_lower_args) + w_new_lower = space.call_method(w_lower, "mutate", w_visitor) space.setattr(w_self, space.wrap("lower"), w_new_lower) w_upper = space.getattr(w_self, space.wrap("upper")) if not space.is_w(w_upper, space.w_None): - w_mutate_upper = space.getattr(w_upper, space.wrap("mutate")) - w_mutate_upper_args = Arguments(space, [ w_visitor ]) - w_new_upper = space.call_args(w_mutate_upper, w_mutate_upper_args) + w_new_upper = space.call_method(w_upper, "mutate", w_visitor) space.setattr(w_self, space.wrap("upper"), w_new_upper) - w_visitSlice = space.getattr(w_visitor, space.wrap("visitSlice")) - w_visitSlice_args = Arguments(space, [ w_self ]) - return space.call_args(w_visitSlice, w_visitSlice_args) + return space.call_method(w_visitor, "visitSlice", w_self) Slice.typedef = TypeDef('Slice', Node.typedef, __new__ = interp2app(descr_Slice_new, unwrap_spec=[ObjSpace, W_Root, W_Root, W_Root, W_Root, W_Root, int]), @@ -5330,25 +4865,19 @@ return space.wrap(self) def descr_Sliceobj_accept( space, w_self, w_visitor): - w_callable = space.getattr(w_visitor, space.wrap('visitSliceobj')) - args = Arguments(space, [ w_self ]) - return space.call_args(w_callable, args) + return space.call_method(w_visitor, 'visitSliceobj', w_self) def descr_Sliceobj_mutate(space, w_self, w_visitor): w_list = space.getattr(w_self, space.wrap("nodes")) list_w = space.unpackiterable(w_list) newlist_w = [] for w_item in list_w: - w_item_mutate = space.getattr(w_item, space.wrap("mutate")) - w_item_mutate_args = Arguments(space, [ w_visitor ]) - w_newitem = space.call_args(w_item_mutate, w_item_mutate_args) + w_newitem = space.call_method(w_item, "mutate", w_visitor) if not space.is_w(w_newitem, space.w_None): newlist_w.append(w_newitem) w_newlist = space.newlist(newlist_w) space.setattr(w_self, space.wrap("nodes"), w_newlist) - w_visitSliceobj = space.getattr(w_visitor, space.wrap("visitSliceobj")) - w_visitSliceobj_args = Arguments(space, [ w_self ]) - return space.call_args(w_visitSliceobj, w_visitSliceobj_args) + return space.call_method(w_visitor, "visitSliceobj", w_self) Sliceobj.typedef = TypeDef('Sliceobj', Node.typedef, __new__ = interp2app(descr_Sliceobj_new, unwrap_spec=[ObjSpace, W_Root, W_Root, int]), @@ -5402,25 +4931,19 @@ return space.wrap(self) def descr_Stmt_accept( space, w_self, w_visitor): - w_callable = space.getattr(w_visitor, space.wrap('visitStmt')) - args = Arguments(space, [ w_self ]) - return space.call_args(w_callable, args) + return space.call_method(w_visitor, 'visitStmt', w_self) def descr_Stmt_mutate(space, w_self, w_visitor): w_list = space.getattr(w_self, space.wrap("nodes")) list_w = space.unpackiterable(w_list) newlist_w = [] for w_item in list_w: - w_item_mutate = space.getattr(w_item, space.wrap("mutate")) - w_item_mutate_args = Arguments(space, [ w_visitor ]) - w_newitem = space.call_args(w_item_mutate, w_item_mutate_args) + w_newitem = space.call_method(w_item, "mutate", w_visitor) if not space.is_w(w_newitem, space.w_None): newlist_w.append(w_newitem) w_newlist = space.newlist(newlist_w) space.setattr(w_self, space.wrap("nodes"), w_newlist) - w_visitStmt = space.getattr(w_visitor, space.wrap("visitStmt")) - w_visitStmt_args = Arguments(space, [ w_self ]) - return space.call_args(w_visitStmt, w_visitStmt_args) + return space.call_method(w_visitor, "visitStmt", w_self) Stmt.typedef = TypeDef('Stmt', Node.typedef, __new__ = interp2app(descr_Stmt_new, unwrap_spec=[ObjSpace, W_Root, W_Root, int]), @@ -5473,26 +4996,18 @@ return space.wrap(self) def descr_Sub_accept( space, w_self, w_visitor): - w_callable = space.getattr(w_visitor, space.wrap('visitSub')) - args = Arguments(space, [ w_self ]) - return space.call_args(w_callable, args) + return space.call_method(w_visitor, 'visitSub', w_self) def descr_Sub_mutate(space, w_self, w_visitor): w_left = space.getattr(w_self, space.wrap("left")) - w_mutate_left = space.getattr(w_left, space.wrap("mutate")) - w_mutate_left_args = Arguments(space, [ w_visitor ]) - w_new_left = space.call_args(w_mutate_left, w_mutate_left_args) + w_new_left = space.call_method(w_left, "mutate", w_visitor) space.setattr(w_self, space.wrap("left"), w_new_left) w_right = space.getattr(w_self, space.wrap("right")) - w_mutate_right = space.getattr(w_right, space.wrap("mutate")) - w_mutate_right_args = Arguments(space, [ w_visitor ]) - w_new_right = space.call_args(w_mutate_right, w_mutate_right_args) + w_new_right = space.call_method(w_right, "mutate", w_visitor) space.setattr(w_self, space.wrap("right"), w_new_right) - w_visitSub = space.getattr(w_visitor, space.wrap("visitSub")) - w_visitSub_args = Arguments(space, [ w_self ]) - return space.call_args(w_visitSub, w_visitSub_args) + return space.call_method(w_visitor, "visitSub", w_self) Sub.typedef = TypeDef('Sub', BinaryOp.typedef, __new__ = interp2app(descr_Sub_new, unwrap_spec=[ObjSpace, W_Root, W_Root, W_Root, int]), @@ -5553,26 +5068,18 @@ return space.wrap(self) def descr_Subscript_accept( space, w_self, w_visitor): - w_callable = space.getattr(w_visitor, space.wrap('visitSubscript')) - args = Arguments(space, [ w_self ]) - return space.call_args(w_callable, args) + return space.call_method(w_visitor, 'visitSubscript', w_self) def descr_Subscript_mutate(space, w_self, w_visitor): w_expr = space.getattr(w_self, space.wrap("expr")) - w_mutate_expr = space.getattr(w_expr, space.wrap("mutate")) - w_mutate_expr_args = Arguments(space, [ w_visitor ]) - w_new_expr = space.call_args(w_mutate_expr, w_mutate_expr_args) + w_new_expr = space.call_method(w_expr, "mutate", w_visitor) space.setattr(w_self, space.wrap("expr"), w_new_expr) w_sub = space.getattr(w_self, space.wrap("sub")) - w_mutate_sub = space.getattr(w_sub, space.wrap("mutate")) - w_mutate_sub_args = Arguments(space, [ w_visitor ]) - w_new_sub = space.call_args(w_mutate_sub, w_mutate_sub_args) + w_new_sub = space.call_method(w_sub, "mutate", w_visitor) space.setattr(w_self, space.wrap("sub"), w_new_sub) - w_visitSubscript = space.getattr(w_visitor, space.wrap("visitSubscript")) - w_visitSubscript_args = Arguments(space, [ w_self ]) - return space.call_args(w_visitSubscript, w_visitSubscript_args) + return space.call_method(w_visitor, "visitSubscript", w_self) Subscript.typedef = TypeDef('Subscript', Node.typedef, __new__ = interp2app(descr_Subscript_new, unwrap_spec=[ObjSpace, W_Root, W_Root, W_Root, W_Root, int]), @@ -5696,15 +5203,11 @@ def descr_TryExcept_accept( space, w_self, w_visitor): - w_callable = space.getattr(w_visitor, space.wrap('visitTryExcept')) - args = Arguments(space, [ w_self ]) - return space.call_args(w_callable, args) + return space.call_method(w_visitor, 'visitTryExcept', w_self) def descr_TryExcept_mutate(space, w_self, w_visitor): w_body = space.getattr(w_self, space.wrap("body")) - w_mutate_body = space.getattr(w_body, space.wrap("mutate")) - w_mutate_body_args = Arguments(space, [ w_visitor ]) - w_new_body = space.call_args(w_mutate_body, w_mutate_body_args) + w_new_body = space.call_method(w_body, "mutate", w_visitor) space.setattr(w_self, space.wrap("body"), w_new_body) w_list = space.getattr(w_self, space.wrap("handlers")) @@ -5716,37 +5219,27 @@ if space.is_w(w_expr1, space.w_None): w_newexpr1 = w_expr1 else: - w_expr1_mutate = space.getattr(w_expr1, space.wrap("mutate")) - w_expr1_mutate_args = Arguments(space, [ w_visitor ]) - w_newexpr1 = space.call_args(w_expr1_mutate, w_expr1_mutate_args) + w_newexpr1 = space.call_method(w_expr1, "mutate", w_visitor) if space.is_w(w_expr2, space.w_None): w_newexpr2 = w_expr2 else: - w_expr2_mutate = space.getattr(w_expr2, space.wrap("mutate")) - w_expr2_mutate_args = Arguments(space, [ w_visitor ]) - w_newexpr2 = space.call_args(w_expr2_mutate, w_expr2_mutate_args) + w_newexpr2 = space.call_method(w_expr2, "mutate", w_visitor) if space.is_w(w_body, space.w_None): w_newbody = w_body else: - w_body_mutate = space.getattr(w_body, space.wrap("mutate")) - w_body_mutate_args = Arguments(space, [ w_visitor ]) - w_newbody = space.call_args(w_body_mutate, w_body_mutate_args) + w_newbody = space.call_method(w_body, "mutate", w_visitor) newlist_w.append(space.newtuple([w_newexpr1, w_newexpr2, w_newbody])) w_newlist = space.newlist(newlist_w) space.setattr(w_self, space.wrap("handlers"), w_newlist) w_else_ = space.getattr(w_self, space.wrap("else_")) if not space.is_w(w_else_, space.w_None): - w_mutate_else_ = space.getattr(w_else_, space.wrap("mutate")) - w_mutate_else__args = Arguments(space, [ w_visitor ]) - w_new_else_ = space.call_args(w_mutate_else_, w_mutate_else__args) + w_new_else_ = space.call_method(w_else_, "mutate", w_visitor) space.setattr(w_self, space.wrap("else_"), w_new_else_) - w_visitTryExcept = space.getattr(w_visitor, space.wrap("visitTryExcept")) - w_visitTryExcept_args = Arguments(space, [ w_self ]) - return space.call_args(w_visitTryExcept, w_visitTryExcept_args) + return space.call_method(w_visitor, "visitTryExcept", w_self) TryExcept.typedef = TypeDef('TryExcept', Node.typedef, @@ -5802,26 +5295,18 @@ return space.wrap(self) def descr_TryFinally_accept( space, w_self, w_visitor): - w_callable = space.getattr(w_visitor, space.wrap('visitTryFinally')) - args = Arguments(space, [ w_self ]) - return space.call_args(w_callable, args) + return space.call_method(w_visitor, 'visitTryFinally', w_self) def descr_TryFinally_mutate(space, w_self, w_visitor): w_body = space.getattr(w_self, space.wrap("body")) - w_mutate_body = space.getattr(w_body, space.wrap("mutate")) - w_mutate_body_args = Arguments(space, [ w_visitor ]) - w_new_body = space.call_args(w_mutate_body, w_mutate_body_args) + w_new_body = space.call_method(w_body, "mutate", w_visitor) space.setattr(w_self, space.wrap("body"), w_new_body) w_final = space.getattr(w_self, space.wrap("final")) - w_mutate_final = space.getattr(w_final, space.wrap("mutate")) - w_mutate_final_args = Arguments(space, [ w_visitor ]) - w_new_final = space.call_args(w_mutate_final, w_mutate_final_args) + w_new_final = space.call_method(w_final, "mutate", w_visitor) space.setattr(w_self, space.wrap("final"), w_new_final) - w_visitTryFinally = space.getattr(w_visitor, space.wrap("visitTryFinally")) - w_visitTryFinally_args = Arguments(space, [ w_self ]) - return space.call_args(w_visitTryFinally, w_visitTryFinally_args) + return space.call_method(w_visitor, "visitTryFinally", w_self) TryFinally.typedef = TypeDef('TryFinally', Node.typedef, __new__ = interp2app(descr_TryFinally_new, unwrap_spec=[ObjSpace, W_Root, W_Root, W_Root, int]), @@ -5876,25 +5361,19 @@ return space.wrap(self) def descr_Tuple_accept( space, w_self, w_visitor): - w_callable = space.getattr(w_visitor, space.wrap('visitTuple')) - args = Arguments(space, [ w_self ]) - return space.call_args(w_callable, args) + return space.call_method(w_visitor, 'visitTuple', w_self) def descr_Tuple_mutate(space, w_self, w_visitor): w_list = space.getattr(w_self, space.wrap("nodes")) list_w = space.unpackiterable(w_list) newlist_w = [] for w_item in list_w: - w_item_mutate = space.getattr(w_item, space.wrap("mutate")) - w_item_mutate_args = Arguments(space, [ w_visitor ]) - w_newitem = space.call_args(w_item_mutate, w_item_mutate_args) + w_newitem = space.call_method(w_item, "mutate", w_visitor) if not space.is_w(w_newitem, space.w_None): newlist_w.append(w_newitem) w_newlist = space.newlist(newlist_w) space.setattr(w_self, space.wrap("nodes"), w_newlist) - w_visitTuple = space.getattr(w_visitor, space.wrap("visitTuple")) - w_visitTuple_args = Arguments(space, [ w_self ]) - return space.call_args(w_visitTuple, w_visitTuple_args) + return space.call_method(w_visitor, "visitTuple", w_self) Tuple.typedef = TypeDef('Tuple', Node.typedef, __new__ = interp2app(descr_Tuple_new, unwrap_spec=[ObjSpace, W_Root, W_Root, int]), @@ -5939,20 +5418,14 @@ return space.wrap(self) def descr_UnaryAdd_accept( space, w_self, w_visitor): - w_callable = space.getattr(w_visitor, space.wrap('visitUnaryAdd')) - args = Arguments(space, [ w_self ]) - return space.call_args(w_callable, args) + return space.call_method(w_visitor, 'visitUnaryAdd', w_self) def descr_UnaryAdd_mutate(space, w_self, w_visitor): w_expr = space.getattr(w_self, space.wrap("expr")) - w_mutate_expr = space.getattr(w_expr, space.wrap("mutate")) - w_mutate_expr_args = Arguments(space, [ w_visitor ]) - w_new_expr = space.call_args(w_mutate_expr, w_mutate_expr_args) + w_new_expr = space.call_method(w_expr, "mutate", w_visitor) space.setattr(w_self, space.wrap("expr"), w_new_expr) - w_visitUnaryAdd = space.getattr(w_visitor, space.wrap("visitUnaryAdd")) - w_visitUnaryAdd_args = Arguments(space, [ w_self ]) - return space.call_args(w_visitUnaryAdd, w_visitUnaryAdd_args) + return space.call_method(w_visitor, "visitUnaryAdd", w_self) UnaryAdd.typedef = TypeDef('UnaryAdd', UnaryOp.typedef, __new__ = interp2app(descr_UnaryAdd_new, unwrap_spec=[ObjSpace, W_Root, W_Root, int]), @@ -5997,20 +5470,14 @@ return space.wrap(self) def descr_UnarySub_accept( space, w_self, w_visitor): - w_callable = space.getattr(w_visitor, space.wrap('visitUnarySub')) - args = Arguments(space, [ w_self ]) - return space.call_args(w_callable, args) + return space.call_method(w_visitor, 'visitUnarySub', w_self) def descr_UnarySub_mutate(space, w_self, w_visitor): w_expr = space.getattr(w_self, space.wrap("expr")) - w_mutate_expr = space.getattr(w_expr, space.wrap("mutate")) - w_mutate_expr_args = Arguments(space, [ w_visitor ]) - w_new_expr = space.call_args(w_mutate_expr, w_mutate_expr_args) + w_new_expr = space.call_method(w_expr, "mutate", w_visitor) space.setattr(w_self, space.wrap("expr"), w_new_expr) - w_visitUnarySub = space.getattr(w_visitor, space.wrap("visitUnarySub")) - w_visitUnarySub_args = Arguments(space, [ w_self ]) - return space.call_args(w_visitUnarySub, w_visitUnarySub_args) + return space.call_method(w_visitor, "visitUnarySub", w_self) UnarySub.typedef = TypeDef('UnarySub', UnaryOp.typedef, __new__ = interp2app(descr_UnarySub_new, unwrap_spec=[ObjSpace, W_Root, W_Root, int]), @@ -6084,33 +5551,23 @@ return space.wrap(self) def descr_While_accept( space, w_self, w_visitor): - w_callable = space.getattr(w_visitor, space.wrap('visitWhile')) - args = Arguments(space, [ w_self ]) - return space.call_args(w_callable, args) + return space.call_method(w_visitor, 'visitWhile', w_self) def descr_While_mutate(space, w_self, w_visitor): w_test = space.getattr(w_self, space.wrap("test")) - w_mutate_test = space.getattr(w_test, space.wrap("mutate")) - w_mutate_test_args = Arguments(space, [ w_visitor ]) - w_new_test = space.call_args(w_mutate_test, w_mutate_test_args) + w_new_test = space.call_method(w_test, "mutate", w_visitor) space.setattr(w_self, space.wrap("test"), w_new_test) w_body = space.getattr(w_self, space.wrap("body")) - w_mutate_body = space.getattr(w_body, space.wrap("mutate")) - w_mutate_body_args = Arguments(space, [ w_visitor ]) - w_new_body = space.call_args(w_mutate_body, w_mutate_body_args) + w_new_body = space.call_method(w_body, "mutate", w_visitor) space.setattr(w_self, space.wrap("body"), w_new_body) w_else_ = space.getattr(w_self, space.wrap("else_")) if not space.is_w(w_else_, space.w_None): - w_mutate_else_ = space.getattr(w_else_, space.wrap("mutate")) - w_mutate_else__args = Arguments(space, [ w_visitor ]) - w_new_else_ = space.call_args(w_mutate_else_, w_mutate_else__args) + w_new_else_ = space.call_method(w_else_, "mutate", w_visitor) space.setattr(w_self, space.wrap("else_"), w_new_else_) - w_visitWhile = space.getattr(w_visitor, space.wrap("visitWhile")) - w_visitWhile_args = Arguments(space, [ w_self ]) - return space.call_args(w_visitWhile, w_visitWhile_args) + return space.call_method(w_visitor, "visitWhile", w_self) While.typedef = TypeDef('While', Node.typedef, __new__ = interp2app(descr_While_new, unwrap_spec=[ObjSpace, W_Root, W_Root, W_Root, W_Root, int]), @@ -6186,33 +5643,23 @@ return space.wrap(self) def descr_With_accept( space, w_self, w_visitor): - w_callable = space.getattr(w_visitor, space.wrap('visitWith')) - args = Arguments(space, [ w_self ]) - return space.call_args(w_callable, args) + return space.call_method(w_visitor, 'visitWith', w_self) def descr_With_mutate(space, w_self, w_visitor): w_expr = space.getattr(w_self, space.wrap("expr")) - w_mutate_expr = space.getattr(w_expr, space.wrap("mutate")) - w_mutate_expr_args = Arguments(space, [ w_visitor ]) - w_new_expr = space.call_args(w_mutate_expr, w_mutate_expr_args) + w_new_expr = space.call_method(w_expr, "mutate", w_visitor) space.setattr(w_self, space.wrap("expr"), w_new_expr) w_body = space.getattr(w_self, space.wrap("body")) - w_mutate_body = space.getattr(w_body, space.wrap("mutate")) - w_mutate_body_args = Arguments(space, [ w_visitor ]) - w_new_body = space.call_args(w_mutate_body, w_mutate_body_args) + w_new_body = space.call_method(w_body, "mutate", w_visitor) space.setattr(w_self, space.wrap("body"), w_new_body) w_var = space.getattr(w_self, space.wrap("var")) if not space.is_w(w_var, space.w_None): - w_mutate_var = space.getattr(w_var, space.wrap("mutate")) - w_mutate_var_args = Arguments(space, [ w_visitor ]) - w_new_var = space.call_args(w_mutate_var, w_mutate_var_args) + w_new_var = space.call_method(w_var, "mutate", w_visitor) space.setattr(w_self, space.wrap("var"), w_new_var) - w_visitWith = space.getattr(w_visitor, space.wrap("visitWith")) - w_visitWith_args = Arguments(space, [ w_self ]) - return space.call_args(w_visitWith, w_visitWith_args) + return space.call_method(w_visitor, "visitWith", w_self) With.typedef = TypeDef('With', Node.typedef, __new__ = interp2app(descr_With_new, unwrap_spec=[ObjSpace, W_Root, W_Root, W_Root, W_Root, int]), @@ -6259,20 +5706,14 @@ return space.wrap(self) def descr_Yield_accept( space, w_self, w_visitor): - w_callable = space.getattr(w_visitor, space.wrap('visitYield')) - args = Arguments(space, [ w_self ]) - return space.call_args(w_callable, args) + return space.call_method(w_visitor, 'visitYield', w_self) def descr_Yield_mutate(space, w_self, w_visitor): w_value = space.getattr(w_self, space.wrap("value")) - w_mutate_value = space.getattr(w_value, space.wrap("mutate")) - w_mutate_value_args = Arguments(space, [ w_visitor ]) - w_new_value = space.call_args(w_mutate_value, w_mutate_value_args) + w_new_value = space.call_method(w_value, "mutate", w_visitor) space.setattr(w_self, space.wrap("value"), w_new_value) - w_visitYield = space.getattr(w_visitor, space.wrap("visitYield")) - w_visitYield_args = Arguments(space, [ w_self ]) - return space.call_args(w_visitYield, w_visitYield_args) + return space.call_method(w_visitor, "visitYield", w_self) Yield.typedef = TypeDef('Yield', Node.typedef, __new__ = interp2app(descr_Yield_new, unwrap_spec=[ObjSpace, W_Root, W_Root, int]), Modified: pypy/dist/pypy/interpreter/astcompiler/ast.txt ============================================================================== --- pypy/dist/pypy/interpreter/astcompiler/ast.txt (original) +++ pypy/dist/pypy/interpreter/astcompiler/ast.txt Wed Dec 13 21:43:32 2006 @@ -320,9 +320,7 @@ def descr_Compare_mutate(space, w_self, w_visitor): w_expr = space.getattr(w_self, space.wrap("expr")) - w_mutate_expr = space.getattr(w_expr, space.wrap("mutate")) - w_mutate_expr_args = Arguments(space, [ w_visitor ]) - w_new_expr = space.call_args(w_mutate_expr, w_mutate_expr_args) + w_new_expr = space.call_method(w_expr, "mutate", w_visitor) space.setattr(w_self, space.wrap("expr"), w_new_expr) w_list = space.getattr(w_self, space.wrap("ops")) @@ -331,16 +329,12 @@ for w_item in list_w: w_opname, w_node = space.unpackiterable(w_item, 2) - w_node_mutate = space.getattr(w_node, space.wrap("mutate")) - w_node_mutate_args = Arguments(space, [ w_visitor ]) - w_newnode = space.call_args(w_node_mutate, w_node_mutate_args) + w_newnode = space.call_method(w_node, "mutate", w_visitor) newlist_w.append(space.newtuple([w_opname, w_newnode])) w_newlist = space.newlist(newlist_w) space.setattr(w_self, space.wrap("ops"), w_newlist) - w_visitCompare = space.getattr(w_visitor, space.wrap("visitCompare")) - w_visitCompare_args = Arguments(space, [ w_self ]) - return space.call_args(w_visitCompare, w_visitCompare_args) + return space.call_method(w_visitor, "visitCompare", w_self) def descr_Dict_new(space, w_subtype, w_items, lineno=-1): @@ -363,20 +357,13 @@ for w_item in list_w: w_key, w_value = space.unpackiterable(w_item, 2) - w_key_mutate = space.getattr(w_key, space.wrap("mutate")) - w_key_mutate_args = Arguments(space, [ w_visitor ]) - w_newkey = space.call_args(w_key_mutate, w_key_mutate_args) - - w_value_mutate = space.getattr(w_value, space.wrap("mutate")) - w_value_mutate_args = Arguments(space, [ w_visitor ]) - w_newvalue = space.call_args(w_value_mutate, w_value_mutate_args) + w_newkey = space.call_method(w_key, "mutate", w_visitor) + w_newvalue = space.call_method(w_value, "mutate", w_visitor) newlist_w.append(space.newtuple([w_newkey, w_newvalue])) w_newlist = space.newlist(newlist_w) space.setattr(w_self, space.wrap("items"), w_newlist) - w_visitDict = space.getattr(w_visitor, space.wrap("visitDict")) - w_visitDict_args = Arguments(space, [ w_self ]) - return space.call_args(w_visitDict, w_visitDict_args) + return space.call_method(w_visitor, "visitDict", w_self) def descr_If_new(space, w_subtype, w_tests, w_else_, lineno=-1): self = space.allocate_instance(If, w_subtype) @@ -399,22 +386,15 @@ for w_item in list_w: w_test, w_suite = space.unpackiterable(w_item, 2) - w_test_mutate = space.getattr(w_test, space.wrap("mutate")) - w_test_mutate_args = Arguments(space, [ w_visitor ]) - w_newtest = space.call_args(w_test_mutate, w_test_mutate_args) - - w_suite_mutate = space.getattr(w_suite, space.wrap("mutate")) - w_suite_mutate_args = Arguments(space, [ w_visitor ]) - w_newsuite = space.call_args(w_suite_mutate, w_suite_mutate_args) + w_newtest = space.call_method(w_test, "mutate", w_visitor) + w_newsuite = space.call_method(w_suite, "mutate", w_visitor) newlist_w.append(space.newtuple([w_newtest, w_newsuite])) w_newlist = space.newlist(newlist_w) space.setattr(w_self, space.wrap("tests"), w_newlist) w_else_ = space.getattr(w_self, space.wrap("else_")) if not space.is_w(w_else_, space.w_None): - w_mutate_else_ = space.getattr(w_else_, space.wrap("mutate")) - w_mutate_else__args = Arguments(space, [ w_visitor ]) - w_new_else_ = space.call_args(w_mutate_else_, w_mutate_else__args) + w_new_else_ = space.call_method(w_else_, "mutate", w_visitor) space.setattr(w_self, space.wrap("else_"), w_new_else_) @@ -437,9 +417,7 @@ def descr_TryExcept_mutate(space, w_self, w_visitor): w_body = space.getattr(w_self, space.wrap("body")) - w_mutate_body = space.getattr(w_body, space.wrap("mutate")) - w_mutate_body_args = Arguments(space, [ w_visitor ]) - w_new_body = space.call_args(w_mutate_body, w_mutate_body_args) + w_new_body = space.call_method(w_body, "mutate", w_visitor) space.setattr(w_self, space.wrap("body"), w_new_body) w_list = space.getattr(w_self, space.wrap("handlers")) @@ -451,34 +429,24 @@ if space.is_w(w_expr1, space.w_None): w_newexpr1 = w_expr1 else: - w_expr1_mutate = space.getattr(w_expr1, space.wrap("mutate")) - w_expr1_mutate_args = Arguments(space, [ w_visitor ]) - w_newexpr1 = space.call_args(w_expr1_mutate, w_expr1_mutate_args) + w_newexpr1 = space.call_method(w_expr1, "mutate", w_visitor) if space.is_w(w_expr2, space.w_None): w_newexpr2 = w_expr2 else: - w_expr2_mutate = space.getattr(w_expr2, space.wrap("mutate")) - w_expr2_mutate_args = Arguments(space, [ w_visitor ]) - w_newexpr2 = space.call_args(w_expr2_mutate, w_expr2_mutate_args) + w_newexpr2 = space.call_method(w_expr2, "mutate", w_visitor) if space.is_w(w_body, space.w_None): w_newbody = w_body else: - w_body_mutate = space.getattr(w_body, space.wrap("mutate")) - w_body_mutate_args = Arguments(space, [ w_visitor ]) - w_newbody = space.call_args(w_body_mutate, w_body_mutate_args) + w_newbody = space.call_method(w_body, "mutate", w_visitor) newlist_w.append(space.newtuple([w_newexpr1, w_newexpr2, w_newbody])) w_newlist = space.newlist(newlist_w) space.setattr(w_self, space.wrap("handlers"), w_newlist) w_else_ = space.getattr(w_self, space.wrap("else_")) if not space.is_w(w_else_, space.w_None): - w_mutate_else_ = space.getattr(w_else_, space.wrap("mutate")) - w_mutate_else__args = Arguments(space, [ w_visitor ]) - w_new_else_ = space.call_args(w_mutate_else_, w_mutate_else__args) + w_new_else_ = space.call_method(w_else_, "mutate", w_visitor) space.setattr(w_self, space.wrap("else_"), w_new_else_) - w_visitTryExcept = space.getattr(w_visitor, space.wrap("visitTryExcept")) - w_visitTryExcept_args = Arguments(space, [ w_self ]) - return space.call_args(w_visitTryExcept, w_visitTryExcept_args) + return space.call_method(w_visitor, "visitTryExcept", w_self) Modified: pypy/dist/pypy/interpreter/astcompiler/astgen.py ============================================================================== --- pypy/dist/pypy/interpreter/astcompiler/astgen.py (original) +++ pypy/dist/pypy/interpreter/astcompiler/astgen.py Wed Dec 13 21:43:32 2006 @@ -384,12 +384,8 @@ print >> buf, ' if not space.is_w(w_%s, space.w_None):' % (argname,) else: indent = '' - print >> buf, indent+' w_mutate_%s = space.getattr(w_%s, space.wrap("mutate"))' % ( argname, - argname) - print >> buf, indent+" w_mutate_%s_args = Arguments(space, [ w_visitor ])"% ( argname ) - print >> buf, indent+" w_new_%s = space.call_args(w_mutate_%s, w_mutate_%s_args)"% ( argname, - argname, - argname) + print >> buf, indent+' w_new_%s = space.call_method(w_%s, "mutate", w_visitor)'% (argname, + argname) print >> buf, indent+' space.setattr(w_self, space.wrap("%s"), w_new_%s)' % ( argname, argname) print >> buf, "" @@ -398,20 +394,14 @@ print >> buf, ' list_w = space.unpackiterable(w_list)' print >> buf, ' newlist_w = []' print >> buf, ' for w_item in list_w:' - print >> buf, ' w_item_mutate = space.getattr(w_item, space.wrap("mutate"))' - print >> buf, ' w_item_mutate_args = Arguments(space, [ w_visitor ])' - print >> buf, ' w_newitem = space.call_args(w_item_mutate, w_item_mutate_args)' + print >> buf, ' w_newitem = space.call_method(w_item, "mutate", w_visitor)' print >> buf, ' if not space.is_w(w_newitem, space.w_None):' print >> buf, ' newlist_w.append(w_newitem)' print >> buf, ' w_newlist = space.newlist(newlist_w)' print >> buf, ' space.setattr(w_self, space.wrap("%s"), w_newlist)'%(argname) - print >> buf, ' w_visit%s = space.getattr(w_visitor, space.wrap("visit%s"))' % (self.name, - self.name) - print >> buf, " w_visit%s_args = Arguments(space, [ w_self ])" % self.name - print >> buf, " return space.call_args(w_visit%s, w_visit%s_args)" % (self.name, - self.name ) + print >> buf, ' return space.call_method(w_visitor, "visit%s", w_self)' % (self.name,) def _gen_typedef(self, buf): @@ -423,9 +413,7 @@ new_unwrap_spec = ['ObjSpace', 'W_Root', 'int'] parent_type = "%s.typedef" % self.parent.name print >> buf, "def descr_%s_accept( space, w_self, w_visitor):" %self.name - print >> buf, " w_callable = space.getattr(w_visitor, space.wrap('visit%s'))" % self.name - print >> buf, " args = Arguments(space, [ w_self ])" - print >> buf, " return space.call_args(w_callable, args)" + print >> buf, " return space.call_method(w_visitor, 'visit%s', w_self)" % self.name print >> buf, "" # mutate stuff @@ -649,7 +637,6 @@ from pypy.interpreter.baseobjspace import Wrappable from pypy.interpreter.typedef import TypeDef, GetSetProperty, interp_attrproperty from pypy.interpreter.gateway import interp2app, W_Root, ObjSpace -from pypy.interpreter.argument import Arguments from pypy.interpreter.error import OperationError def flatten(list): @@ -709,14 +696,10 @@ return space.newlist( [ space.wrap( it ) for it in lst ] ) def descr_node_accept( space, w_self, w_visitor ): - w_callable = space.getattr(w_visitor, space.wrap('visitNode')) - args = Arguments(space, [ w_self ]) - return space.call_args( w_callable, args ) + return space.call_method( w_visitor, 'visitNode', w_self ) def descr_node_mutate(space, w_self, w_visitor): - w_visitNode = space.getattr(w_visitor, space.wrap("visitNode")) - w_visitNode_args = Arguments(space, [ w_self ]) - return space.call_args(w_visitNode, w_visitNode_args) + return space.call_method(w_visitor, 'visitNode', w_self) def descr_Node_new(space, w_subtype, lineno=-1): node = space.allocate_instance(Node, w_subtype) @@ -774,20 +757,14 @@ return space.wrap(self) def descr_expression_accept(space, w_self, w_visitor): - w_callable = space.getattr(w_visitor, space.wrap("visitExpression")) - args = Arguments(space, [ w_self ]) - return space.call_args(w_callable, args) + return space.call_method(w_visitor, 'visitExpression', w_self) def descr_expression_mutate(space, w_self, w_visitor): w_node = space.getattr(w_self, space.wrap("node")) - w_mutate_node = space.getattr(w_node, space.wrap("mutate")) - w_mutate_node_args = Arguments(space, [ w_visitor ]) - w_new_node = space.call_args(w_mutate_node, w_mutate_node_args) + w_new_node = space.call_method(w_node, "mutate", w_visitor) space.setattr(w_self, space.wrap("node"), w_new_node) - w_visitExpression = space.getattr(w_visitor, space.wrap("visitExpression")) - w_visitExpression_args = Arguments(space, [ w_self ]) - return space.call_args(w_visitExpression, w_visitExpression_args) + return space.call_method(w_visitor, "visitExpression", w_self) Expression.typedef = TypeDef('Expression', Node.typedef, __new__ = interp2app(descr_expression_new, unwrap_spec=[ObjSpace, W_Root, W_Root, int]), From pedronis at codespeak.net Wed Dec 13 21:49:54 2006 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Wed, 13 Dec 2006 21:49:54 +0100 (CET) Subject: [pypy-svn] r35705 - pypy/dist/pypy/doc Message-ID: <20061213204954.8E83E100A7@code0.codespeak.net> Author: pedronis Date: Wed Dec 13 21:49:53 2006 New Revision: 35705 Modified: pypy/dist/pypy/doc/draft-jit-outline.txt Log: rewording Modified: pypy/dist/pypy/doc/draft-jit-outline.txt ============================================================================== --- pypy/dist/pypy/doc/draft-jit-outline.txt (original) +++ pypy/dist/pypy/doc/draft-jit-outline.txt Wed Dec 13 21:49:53 2006 @@ -273,7 +273,7 @@ should be able to produce code that unfolds the loop and respectively folds instruction dispatching (the ifs) at compile-time, because the while condition, the ``pc`` increment, and the dispatching are -operations among only greens (constants are green by default). +operations between greens only (constants are green by default). Calls ---------------------------------- From arigo at codespeak.net Wed Dec 13 21:55:36 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 13 Dec 2006 21:55:36 +0100 (CET) Subject: [pypy-svn] r35706 - pypy/dist/pypy/doc Message-ID: <20061213205536.BD16F100AA@code0.codespeak.net> Author: arigo Date: Wed Dec 13 21:55:35 2006 New Revision: 35706 Modified: pypy/dist/pypy/doc/draft-jit-outline.txt Log: rerewording Modified: pypy/dist/pypy/doc/draft-jit-outline.txt ============================================================================== --- pypy/dist/pypy/doc/draft-jit-outline.txt (original) +++ pypy/dist/pypy/doc/draft-jit-outline.txt Wed Dec 13 21:55:35 2006 @@ -269,11 +269,12 @@ The result ``op`` compared to the possible "instructions" will also be green. Because ``s`` is green also ``len(s)`` will be. -Using this information the *timeshifting* of the ``ll_plus_minus``, -should be able to produce code that unfolds the loop and respectively -folds instruction dispatching (the ifs) at compile-time, because the -while condition, the ``pc`` increment, and the dispatching are -operations between greens only (constants are green by default). +As we will see later, the timeshifter_ can use this information to +generate code that unfolds the loop (because the ``while`` condition is +green) and folds instruction dispatching (because the ``if`` conditions +are green) at compile-time. In other words, the only operations left +involving red variables are ``acc += y`` and ``acc -= y``, so only these +operations will eventually appear in the residual graph. Calls ---------------------------------- @@ -358,6 +359,7 @@ +.. _timeshifter: .. _timeshifting: Timeshifting: transforming interpreter into compilers From arigo at codespeak.net Wed Dec 13 22:17:12 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 13 Dec 2006 22:17:12 +0100 (CET) Subject: [pypy-svn] r35707 - pypy/dist/pypy Message-ID: <20061213211712.4B00110087@code0.codespeak.net> Author: arigo Date: Wed Dec 13 22:17:10 2006 New Revision: 35707 Modified: pypy/dist/pypy/conftest.py Log: py.test -A: detect objspace mismatch and skip. Modified: pypy/dist/pypy/conftest.py ============================================================================== --- pypy/dist/pypy/conftest.py (original) +++ pypy/dist/pypy/conftest.py Wed Dec 13 22:17:10 2006 @@ -32,6 +32,11 @@ return _SPACECACHE[key] except KeyError: if option.runappdirect: + if name not in (None, 'std'): + myname = getattr(sys, 'pypy_objspaceclass', '') + if not myname.lower().startswith(name): + py.test.skip("cannot runappdirect test: " + "%s objspace required" % (name,)) return TinyObjSpace(**kwds) try: space = make_objspace(config) From arigo at codespeak.net Wed Dec 13 22:17:32 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 13 Dec 2006 22:17:32 +0100 (CET) Subject: [pypy-svn] r35708 - in pypy/dist/pypy: interpreter module/_stackless Message-ID: <20061213211732.8DF811008E@code0.codespeak.net> Author: arigo Date: Wed Dec 13 22:17:28 2006 New Revision: 35708 Modified: pypy/dist/pypy/interpreter/argument.py pypy/dist/pypy/module/_stackless/interp_greenlet.py Log: This argument could never actually be None. Modified: pypy/dist/pypy/interpreter/argument.py ============================================================================== --- pypy/dist/pypy/interpreter/argument.py (original) +++ pypy/dist/pypy/interpreter/argument.py Wed Dec 13 22:17:28 2006 @@ -322,7 +322,7 @@ ### Construction ### - def __init__(self, space, args_w=None, kwds_w=None, + def __init__(self, space, args_w, kwds_w=None, w_stararg=None, w_starstararg=None): self.space = space self.arguments_w = args_w Modified: pypy/dist/pypy/module/_stackless/interp_greenlet.py ============================================================================== --- pypy/dist/pypy/module/_stackless/interp_greenlet.py (original) +++ pypy/dist/pypy/module/_stackless/interp_greenlet.py Wed Dec 13 22:17:28 2006 @@ -103,8 +103,6 @@ self.costate.operr = None raise operr args_w, kwds_w = self.costate.__args__.unpack() - if args_w is None: - return self.space.w_None if len(args_w) == 1: return args_w[0] return self.space.newtuple(args_w) From arigo at codespeak.net Wed Dec 13 22:45:40 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 13 Dec 2006 22:45:40 +0100 (CET) Subject: [pypy-svn] r35709 - in pypy/dist/pypy/annotation: . test Message-ID: <20061213214540.34B9C10079@code0.codespeak.net> Author: arigo Date: Wed Dec 13 22:45:38 2006 New Revision: 35709 Modified: pypy/dist/pypy/annotation/builtin.py pypy/dist/pypy/annotation/test/test_annrpython.py Log: max(nonneg, *whatever) always returns a nonneg. This is very much a just-because check-in. Modified: pypy/dist/pypy/annotation/builtin.py ============================================================================== --- pypy/dist/pypy/annotation/builtin.py (original) +++ pypy/dist/pypy/annotation/builtin.py Wed Dec 13 22:45:38 2006 @@ -218,7 +218,19 @@ else: return unionof(*s_values) -builtin_max = builtin_min +def builtin_max(*s_values): + if len(s_values) == 1: # xxx do we support this? + s_iter = s_values[0].iter() + return s_iter.next() + else: + s = unionof(*s_values) + if type(s) is SomeInteger: + nonneg = False + for s1 in s_values: + nonneg |= s1.nonneg + if nonneg: + s = SomeInteger(nonneg=True, knowntype=s.knowntype) + return s def builtin_apply(*stuff): getbookkeeper().warning("ignoring apply%r" % (stuff,)) Modified: pypy/dist/pypy/annotation/test/test_annrpython.py ============================================================================== --- pypy/dist/pypy/annotation/test/test_annrpython.py (original) +++ pypy/dist/pypy/annotation/test/test_annrpython.py Wed Dec 13 22:45:38 2006 @@ -1417,7 +1417,14 @@ wg2 = graphof(a, witness2) assert a.binding(wg1.getargs()[0]).knowntype is r_ulonglong assert a.binding(wg2.getargs()[0]).knowntype is r_ulonglong - + + def test_nonneg_cleverness_in_max(self): + def f(x): + return max(x, 0) + max(0, x) + a = self.RPythonAnnotator() + s = a.build_types(f, [int]) + assert s.nonneg + def test_attr_moving_into_parent(self): class A: pass class B(A): pass From arigo at codespeak.net Wed Dec 13 22:47:00 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 13 Dec 2006 22:47:00 +0100 (CET) Subject: [pypy-svn] r35710 - pypy/dist/pypy/annotation Message-ID: <20061213214700.B035910077@code0.codespeak.net> Author: arigo Date: Wed Dec 13 22:46:59 2006 New Revision: 35710 Modified: pypy/dist/pypy/annotation/builtin.py Log: Minor fix to preserve the 'const' attribute if possible. Modified: pypy/dist/pypy/annotation/builtin.py ============================================================================== --- pypy/dist/pypy/annotation/builtin.py (original) +++ pypy/dist/pypy/annotation/builtin.py Wed Dec 13 22:46:59 2006 @@ -224,7 +224,7 @@ return s_iter.next() else: s = unionof(*s_values) - if type(s) is SomeInteger: + if type(s) is SomeInteger and not s.nonneg: nonneg = False for s1 in s_values: nonneg |= s1.nonneg From arigo at codespeak.net Wed Dec 13 23:22:21 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 13 Dec 2006 23:22:21 +0100 (CET) Subject: [pypy-svn] r35711 - in pypy/dist/pypy: rpython/lltypesystem translator/cli translator/js translator/jvm translator/squeak Message-ID: <20061213222221.B9EC910077@code0.codespeak.net> Author: arigo Date: Wed Dec 13 23:22:17 2006 New Revision: 35711 Modified: pypy/dist/pypy/rpython/lltypesystem/lloperation.py pypy/dist/pypy/rpython/lltypesystem/opimpl.py pypy/dist/pypy/translator/cli/opcodes.py pypy/dist/pypy/translator/js/opcodes.py pypy/dist/pypy/translator/jvm/opcodes.py pypy/dist/pypy/translator/squeak/opformatter.py Log: issue192 resolved Remove the three obscure float operations that were never produced anyway. Modified: pypy/dist/pypy/rpython/lltypesystem/lloperation.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/lloperation.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/lloperation.py Wed Dec 13 23:22:17 2006 @@ -114,10 +114,9 @@ # ____________________________________________________________ # # This list corresponds to the operations implemented by the LLInterpreter. -# XXX Some clean-ups are needed: -# * many exception-raising operations are being replaced by calls to helpers -# * float_mod vs float_fmod ? -# Run test_lloperation after changes. Feel free to clean up LLInterpreter too :-) +# Note that many exception-raising operations are being replaced by calls +# to helpers by rpython/raisingops/. +# ***** Run test_lloperation after changes. ***** LL_OPERATIONS = { @@ -210,15 +209,12 @@ 'float_sub': LLOp(canfold=True), 'float_mul': LLOp(canfold=True), 'float_truediv': LLOp(canfold=True), - 'float_mod': LLOp(canfold=True), 'float_lt': LLOp(canfold=True), 'float_le': LLOp(canfold=True), 'float_eq': LLOp(canfold=True), 'float_ne': LLOp(canfold=True), 'float_gt': LLOp(canfold=True), 'float_ge': LLOp(canfold=True), - 'float_floor': LLOp(canfold=True), # XXX not used? - 'float_fmod': LLOp(canfold=True), # XXX not used? 'float_pow': LLOp(canfold=True), 'llong_is_true': LLOp(canfold=True), Modified: pypy/dist/pypy/rpython/lltypesystem/opimpl.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/opimpl.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/opimpl.py Wed Dec 13 23:22:17 2006 @@ -232,15 +232,6 @@ assert -sys.maxint-1 <= b <= sys.maxint return int(b) -def op_float_floor(b): - assert type(b) is float - return math.floor(b) - -def op_float_fmod(b,c): - assert type(b) is float - assert type(c) is float - return math.fmod(b,c) - def op_float_pow(b,c): assert type(b) is float assert type(c) is float Modified: pypy/dist/pypy/translator/cli/opcodes.py ============================================================================== --- pypy/dist/pypy/translator/cli/opcodes.py (original) +++ pypy/dist/pypy/translator/cli/opcodes.py Wed Dec 13 23:22:17 2006 @@ -154,15 +154,12 @@ 'float_sub': 'sub', 'float_mul': 'mul', 'float_truediv': 'div', - 'float_mod': 'rem', 'float_lt': 'clt', 'float_le': _not('cgt'), 'float_eq': 'ceq', 'float_ne': _not('ceq'), 'float_gt': 'cgt', 'float_ge': _not('clt'), - 'float_floor': None, # TODO - 'float_fmod': None, # TODO 'llong_is_true': [PushAllArgs, 'ldc.i8 0', 'cgt.un'], 'llong_neg': 'neg', Modified: pypy/dist/pypy/translator/js/opcodes.py ============================================================================== --- pypy/dist/pypy/translator/js/opcodes.py (original) +++ pypy/dist/pypy/translator/js/opcodes.py Wed Dec 13 23:22:17 2006 @@ -82,7 +82,6 @@ 'float_add': '+', 'float_sub': '-', 'float_truediv': '/', - 'float_mod': '%', 'float_lt': '<', 'float_le': '<=', 'float_eq': '==', Modified: pypy/dist/pypy/translator/jvm/opcodes.py ============================================================================== --- pypy/dist/pypy/translator/jvm/opcodes.py (original) +++ pypy/dist/pypy/translator/jvm/opcodes.py Wed Dec 13 23:22:17 2006 @@ -141,15 +141,12 @@ 'float_sub': jvmgen.DSUB, 'float_mul': jvmgen.DMUL, 'float_truediv': jvmgen.DDIV, - 'float_mod': jvmgen.DREM, # use Math.IEEEremainder? 'float_lt': 'dbl_less_than', 'float_le': 'dbl_less_equals', 'float_eq': 'dbl_equals', 'float_ne': 'dbl_not_equals', 'float_gt': 'dbl_greater_than', 'float_ge': 'dbl_greater_equals', - 'float_floor': jvmgen.MATHFLOOR, - 'float_fmod': jvmgen.DREM, # DREM is akin to fmod() in C 'llong_is_true': [PushAllArgs, jvmgen.LCONST_0, Modified: pypy/dist/pypy/translator/squeak/opformatter.py ============================================================================== --- pypy/dist/pypy/translator/squeak/opformatter.py (original) +++ pypy/dist/pypy/translator/squeak/opformatter.py Wed Dec 13 23:22:17 2006 @@ -32,8 +32,6 @@ 'bool_not': 'not', 'cast_int_to_float': 'asFloat', - 'float_fmod': r'\\', # we can't really distinguish mod and fmod - 'float_floor': 'floor', # XXX this potentially incorrect (may return LargeIntegers) 'cast_float_to_int': 'truncated', } From arigo at codespeak.net Wed Dec 13 23:27:28 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 13 Dec 2006 23:27:28 +0100 (CET) Subject: [pypy-svn] r35712 - pypy/dist/pypy/lib Message-ID: <20061213222728.5662810077@code0.codespeak.net> Author: arigo Date: Wed Dec 13 23:27:26 2006 New Revision: 35712 Modified: pypy/dist/pypy/lib/md5.py Log: Fix broken encoding line. Modified: pypy/dist/pypy/lib/md5.py ============================================================================== --- pypy/dist/pypy/lib/md5.py (original) +++ pypy/dist/pypy/lib/md5.py Wed Dec 13 23:27:26 2006 @@ -1,5 +1,5 @@ #!/usr/bin/env python -# -*- coding: iso-8859-1 +# -*- coding: iso-8859-1 -*- """A sample implementation of MD5 in pure Python. From arigo at codespeak.net Wed Dec 13 23:33:38 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 13 Dec 2006 23:33:38 +0100 (CET) Subject: [pypy-svn] r35713 - pypy/dist/pypy/lib Message-ID: <20061213223338.DB42010084@code0.codespeak.net> Author: arigo Date: Wed Dec 13 23:33:37 2006 New Revision: 35713 Modified: pypy/dist/pypy/lib/md5.py Log: Remove a complicated helper that is not used in an essential way. Modified: pypy/dist/pypy/lib/md5.py ============================================================================== --- pypy/dist/pypy/lib/md5.py (original) +++ pypy/dist/pypy/lib/md5.py Wed Dec 13 23:33:37 2006 @@ -39,47 +39,8 @@ # ====================================================================== # Bit-Manipulation helpers -# -# _long2bytes() was contributed by Barry Warsaw -# and is reused here with tiny modifications. # ====================================================================== -def _long2bytes(n, blocksize=0): - """Convert a long integer to a byte string. - - If optional blocksize is given and greater than zero, pad the front - of the byte string with binary zeros so that the length is a multiple - of blocksize. - """ - - # After much testing, this algorithm was deemed to be the fastest. - s = '' - pack = struct.pack - while n > 0: - ### CHANGED FROM '>I' TO '> 32 - - # Strip off leading zeros. - for i in range(len(s)): - if s[i] <> '\000': - break - else: - # Only happens when n == 0. - s = '\000' - i = 0 - - s = s[i:] - - # Add back some pad bytes. This could be done more efficiently - # w.r.t. the de-padding being done above, but sigh... - if blocksize > 0 and len(s) % blocksize: - s = (blocksize - len(s) % blocksize) * '\000' + s - - return s - - def _bytelist2long(list): "Transform a list of characters into a list of longs." @@ -358,10 +319,10 @@ self._transform(bits) # Store state in digest. - digest = _long2bytes(self.A << 96, 16)[:4] + \ - _long2bytes(self.B << 64, 16)[4:8] + \ - _long2bytes(self.C << 32, 16)[8:12] + \ - _long2bytes(self.D, 16)[12:] + digest = (struct.pack(" Author: pedronis Date: Thu Dec 14 02:01:08 2006 New Revision: 35715 Modified: pypy/dist/pypy/objspace/std/strutil.py pypy/dist/pypy/objspace/std/test/test_strutil.py pypy/dist/pypy/rlib/rarithmetic.py pypy/dist/pypy/rlib/test/test_rarithmetic.py Log: move break_up_float to rarithmetic where parts_to_float already lives. After the move it raises ValueError! Preparation for supporting in RPython directly float(string). Modified: pypy/dist/pypy/objspace/std/strutil.py ============================================================================== --- pypy/dist/pypy/objspace/std/strutil.py (original) +++ pypy/dist/pypy/objspace/std/strutil.py Thu Dec 14 02:01:08 2006 @@ -2,7 +2,7 @@ Pure Python implementation of string utilities. """ -from pypy.rlib.rarithmetic import ovfcheck, parts_to_float +from pypy.rlib.rarithmetic import ovfcheck, break_up_float, parts_to_float from pypy.interpreter.error import OperationError import math @@ -139,58 +139,6 @@ return w_result w_result = space.add(space.mul(w_result,w_base), space.newlong(digit)) -def break_up_float(s): - i = 0 - - sign = '' - before_point = '' - after_point = '' - exponent = '' - - if s[i] in '+-': - sign = s[i] - i += 1 - - while i < len(s) and s[i] in '0123456789': - before_point += s[i] - i += 1 - - if i == len(s): - return sign, before_point, after_point, exponent - - if s[i] == '.': - i += 1 - while i < len(s) and s[i] in '0123456789': - after_point += s[i] - i += 1 - - if i == len(s): - return sign, before_point, after_point, exponent - - if s[i] not in 'eE': - raise ParseStringError("invalid literal for float()") - - i += 1 - if i == len(s): - raise ParseStringError("invalid literal for float()") - - if s[i] in '-+': - exponent += s[i] - i += 1 - - if i == len(s): - raise ParseStringError("invalid literal for float()") - - while i < len(s) and s[i] in '0123456789': - exponent += s[i] - i += 1 - - if i != len(s): - raise ParseStringError("invalid literal for float()") - - return sign, before_point, after_point, exponent - - def string_to_float(s): """ Conversion of string to float. @@ -204,7 +152,10 @@ raise ParseStringError("empty string for float()") # 1) parse the string into pieces. - sign, before_point, after_point, exponent = break_up_float(s) + try: + sign, before_point, after_point, exponent = break_up_float(s) + except ValueError: + raise ParseStringError("invalid literal for float()") if not before_point and not after_point: raise ParseStringError("invalid literal for float()") @@ -291,8 +242,11 @@ raise ParseStringError("empty string for float()") # 1) parse the string into pieces. - sign, before_point, after_point, exponent = break_up_float(s) - + try: + sign, before_point, after_point, exponent = break_up_float(s) + except ValueError: + raise ParseStringError("invalid literal for float()") + digits = before_point + after_point if digits: raise ParseStringError("invalid literal for float()") @@ -384,7 +338,10 @@ "empty string for float()")) # 1) parse the string into pieces. - sign, before_point, after_point, exponent = break_up_float(s) + try: + sign, before_point, after_point, exponent = break_up_float(s) + except ValueError: + raise ParseStringError("invalid literal for float()") digits = before_point + after_point if not digits: Modified: pypy/dist/pypy/objspace/std/test/test_strutil.py ============================================================================== --- pypy/dist/pypy/objspace/std/test/test_strutil.py (original) +++ pypy/dist/pypy/objspace/std/test/test_strutil.py Thu Dec 14 02:01:08 2006 @@ -127,27 +127,6 @@ assert string_to_w_long(space, '123L', 21).longval() == 441 + 42 + 3 assert string_to_w_long(space, '1891234174197319').longval() == 1891234174197319 - -def test_break_up_float(): - assert break_up_float('1') == ('', '1', '', '') - assert break_up_float('+1') == ('+', '1', '', '') - assert break_up_float('-1') == ('-', '1', '', '') - - assert break_up_float('.5') == ('', '', '5', '') - - assert break_up_float('1.2e3') == ('', '1', '2', '3') - assert break_up_float('1.2e+3') == ('', '1', '2', '+3') - assert break_up_float('1.2e-3') == ('', '1', '2', '-3') - - # some that will get thrown out on return: - assert break_up_float('.') == ('', '', '', '') - assert break_up_float('+') == ('+', '', '', '') - assert break_up_float('-') == ('-', '', '', '') - assert break_up_float('e1') == ('', '', '', '1') - - py.test.raises(ParseStringError, break_up_float, 'e') - - def test_string_to_float(): assert string_to_float('0') == 0.0 assert string_to_float('1') == 1.0 Modified: pypy/dist/pypy/rlib/rarithmetic.py ============================================================================== --- pypy/dist/pypy/rlib/rarithmetic.py (original) +++ pypy/dist/pypy/rlib/rarithmetic.py Thu Dec 14 02:01:08 2006 @@ -337,6 +337,60 @@ r_longlong = build_int('r_longlong', True, 64) r_ulonglong = build_int('r_ulonglong', False, 64) + +# float as string -> sign, beforept, afterpt, exponent + +def break_up_float(s): + i = 0 + + sign = '' + before_point = '' + after_point = '' + exponent = '' + + if s[i] in '+-': + sign = s[i] + i += 1 + + while i < len(s) and s[i] in '0123456789': + before_point += s[i] + i += 1 + + if i == len(s): + return sign, before_point, after_point, exponent + + if s[i] == '.': + i += 1 + while i < len(s) and s[i] in '0123456789': + after_point += s[i] + i += 1 + + if i == len(s): + return sign, before_point, after_point, exponent + + if s[i] not in 'eE': + raise ValueError + + i += 1 + if i == len(s): + raise ValueError + + if s[i] in '-+': + exponent += s[i] + i += 1 + + if i == len(s): + raise ValueError + + while i < len(s) and s[i] in '0123456789': + exponent += s[i] + i += 1 + + if i != len(s): + raise ValueError + + return sign, before_point, after_point, exponent + # string -> float helper def parts_to_float(sign, beforept, afterpt, exponent): Modified: pypy/dist/pypy/rlib/test/test_rarithmetic.py ============================================================================== --- pypy/dist/pypy/rlib/test/test_rarithmetic.py (original) +++ pypy/dist/pypy/rlib/test/test_rarithmetic.py Thu Dec 14 02:01:08 2006 @@ -267,6 +267,25 @@ assert type(abs(r_longlong(1))) is r_longlong +def test_break_up_float(): + assert break_up_float('1') == ('', '1', '', '') + assert break_up_float('+1') == ('+', '1', '', '') + assert break_up_float('-1') == ('-', '1', '', '') + + assert break_up_float('.5') == ('', '', '5', '') + + assert break_up_float('1.2e3') == ('', '1', '2', '3') + assert break_up_float('1.2e+3') == ('', '1', '2', '+3') + assert break_up_float('1.2e-3') == ('', '1', '2', '-3') + + # some that will get thrown out on return: + assert break_up_float('.') == ('', '', '', '') + assert break_up_float('+') == ('+', '', '', '') + assert break_up_float('-') == ('-', '', '', '') + assert break_up_float('e1') == ('', '', '', '1') + + py.test.raises(ValueError, break_up_float, 'e') + class BaseTestRarithmetic(BaseRtypingTest): def test_formatd(self): from pypy.rlib.rarithmetic import formatd @@ -275,6 +294,20 @@ res = self.ll_to_string(self.interpret(f, [10/3.0])) assert res == '3.33' + def test_parts_to_float(self): + from pypy.rlib.rarithmetic import parts_to_float, break_up_float + def f(x): + if x == 0: + s = '1.0' + else: + s = '1e-100' + sign, beforept, afterpt, expt = break_up_float(s) + return parts_to_float(sign, beforept, afterpt, expt) + res = self.interpret(f, [0]) + assert res == 1.0 + + res = self.interpret(f, [1]) + assert res == 1e-100 class TestLLtype(BaseTestRarithmetic, LLRtypeMixin): pass From pedronis at codespeak.net Thu Dec 14 02:04:43 2006 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Thu, 14 Dec 2006 02:04:43 +0100 (CET) Subject: [pypy-svn] r35716 - in pypy/dist/pypy: rpython/lltypesystem/module rpython/module rpython/module/test rpython/ootypesystem/module translator/c Message-ID: <20061214010443.2DEE510075@code0.codespeak.net> Author: pedronis Date: Thu Dec 14 02:04:40 2006 New Revision: 35716 Modified: pypy/dist/pypy/rpython/lltypesystem/module/ll_strtod.py pypy/dist/pypy/rpython/module/ll_strtod.py pypy/dist/pypy/rpython/module/test/test_ll_strtod.py pypy/dist/pypy/rpython/ootypesystem/module/ll_strtod.py pypy/dist/pypy/translator/c/extfunc.py Log: preparation for float(string): for consistency make parts_to_float a suggested primitive for oo backend too. Modified: pypy/dist/pypy/rpython/lltypesystem/module/ll_strtod.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/module/ll_strtod.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/module/ll_strtod.py Thu Dec 14 02:04:40 2006 @@ -7,3 +7,11 @@ return LLSupport.to_rstr(rarithmetic.formatd(LLSupport.from_rstr(fmt), x)) ll_strtod_formatd.suggested_primitive = True ll_strtod_formatd = staticmethod(ll_strtod_formatd) + + def ll_strtod_parts_to_float(sign, beforept, afterpt, exponent): + return rarithmetic.parts_to_float(LLSupport.from_rstr(sign), + LLSupport.from_rstr(beforept), + LLSupport.from_rstr(afterpt), + LLSupport.from_rstr(exponent)) + ll_strtod_parts_to_float.suggested_primitive = True + ll_strtod_parts_to_float = staticmethod(ll_strtod_parts_to_float) Modified: pypy/dist/pypy/rpython/module/ll_strtod.py ============================================================================== --- pypy/dist/pypy/rpython/module/ll_strtod.py (original) +++ pypy/dist/pypy/rpython/module/ll_strtod.py Thu Dec 14 02:04:40 2006 @@ -1,12 +1,3 @@ -# string -> float helper -from pypy.rlib import rarithmetic -from pypy.rpython.module.support import LLSupport, ll_strcpy -def ll_strtod_parts_to_float(sign, beforept, afterpt, exponent): - return rarithmetic.parts_to_float(LLSupport.from_rstr(sign), - LLSupport.from_rstr(beforept), - LLSupport.from_rstr(afterpt), - LLSupport.from_rstr(exponent)) -ll_strtod_parts_to_float.suggested_primitive = True Modified: pypy/dist/pypy/rpython/module/test/test_ll_strtod.py ============================================================================== --- pypy/dist/pypy/rpython/module/test/test_ll_strtod.py (original) +++ pypy/dist/pypy/rpython/module/test/test_ll_strtod.py Thu Dec 14 02:04:40 2006 @@ -1,23 +1,36 @@ +import py -from pypy.rpython.module.ll_strtod import ll_strtod_parts_to_float -from pypy.rpython.module.support import LLSupport -from pypy.rpython.lltypesystem.module.ll_strtod import Implementation - - -def test_parts_to_float(): - data = [ - (("","1","","") , 1.0), - (("-","1","","") , -1.0), - (("-","1","5","") , -1.5), - (("-","1","5","2") , -1.5e2), - (("-","1","5","+2") , -1.5e2), - (("-","1","5","-2") , -1.5e-2), - ] - - for parts, val in data: - assert ll_strtod_parts_to_float(*map(LLSupport.to_rstr, parts)) == val +class BaseTest(object): + def test_parts_to_float(self): + #py.test.skip("wip") + Support = self.Support + Impl = self.Implementation + + data = [ + (("","1","","") , 1.0), + (("-","1","","") , -1.0), + (("-","1","5","") , -1.5), + (("-","1","5","2") , -1.5e2), + (("-","1","5","+2") , -1.5e2), + (("-","1","5","-2") , -1.5e-2), + ] + + for parts, val in data: + assert Impl.ll_strtod_parts_to_float(*map(Support.to_rstr, parts)) == val + + + def test_formatd(self): + Support = self.Support + Impl = self.Implementation + + res = Impl.ll_strtod_formatd(Support.to_rstr("%.2f"), 1.5) + assert Support.from_rstr(res) == "1.50" + +class TestLL(BaseTest): + from pypy.rpython.module.support import LLSupport as Support + from pypy.rpython.lltypesystem.module.ll_strtod import Implementation -def test_formatd(): - res = Implementation.ll_strtod_formatd(LLSupport.to_rstr("%.2f"), 1.5) - assert LLSupport.from_rstr(res) == "1.50" +class TestOO(BaseTest): + from pypy.rpython.module.support import OOSupport as Support + from pypy.rpython.ootypesystem.module.ll_strtod import Implementation Modified: pypy/dist/pypy/rpython/ootypesystem/module/ll_strtod.py ============================================================================== --- pypy/dist/pypy/rpython/ootypesystem/module/ll_strtod.py (original) +++ pypy/dist/pypy/rpython/ootypesystem/module/ll_strtod.py Thu Dec 14 02:04:40 2006 @@ -8,3 +8,11 @@ def ll_strtod_formatd(cls, fmt, x): return cls.to_rstr(rarithmetic.formatd(cls.from_rstr(fmt), x)) ll_strtod_formatd.suggested_primitive = True + + + def ll_strtod_parts_to_float(cls, sign, beforept, afterpt, exponent): + return rarithmetic.parts_to_float(cls.from_rstr(sign), + cls.from_rstr(beforept), + cls.from_rstr(afterpt), + cls.from_rstr(exponent)) + ll_strtod_parts_to_float.suggested_primitive = True Modified: pypy/dist/pypy/translator/c/extfunc.py ============================================================================== --- pypy/dist/pypy/translator/c/extfunc.py (original) +++ pypy/dist/pypy/translator/c/extfunc.py Thu Dec 14 02:04:40 2006 @@ -5,14 +5,14 @@ from pypy.rpython.lltypesystem.rstr import STR, mallocstr from pypy.rpython.lltypesystem import rstr from pypy.rpython.lltypesystem import rlist -from pypy.rpython.module import ll_time, ll_math, ll_strtod +from pypy.rpython.module import ll_time, ll_math from pypy.rpython.module import ll_stackless, ll_stack from pypy.rpython.module.support import ll_execve from pypy.rpython.lltypesystem.module.ll_os import STAT_RESULT, PIPE_RESULT from pypy.rpython.lltypesystem.module.ll_os import WAITPID_RESULT from pypy.rpython.lltypesystem.module.ll_os import Implementation as impl from pypy.rpython.lltypesystem.module import ll_math as ll_math2 -from pypy.rpython.lltypesystem.module import ll_strtod as ll_strtod2 +from pypy.rpython.lltypesystem.module import ll_strtod from pypy.rlib import ros try: @@ -74,9 +74,9 @@ ll_math.ll_math_ldexp: 'LL_math_ldexp', ll_math2.Implementation.ll_math_modf.im_func: 'LL_math_modf', ll_math.ll_math_hypot: 'LL_math_hypot', - ll_strtod.ll_strtod_parts_to_float: + ll_strtod.Implementation.ll_strtod_parts_to_float: 'LL_strtod_parts_to_float', - ll_strtod2.Implementation.ll_strtod_formatd: + ll_strtod.Implementation.ll_strtod_formatd: 'LL_strtod_formatd', ll_stackless.ll_stackless_switch: 'LL_stackless_switch', ll_stackless.ll_stackless_stack_frames_depth: 'LL_stackless_stack_frames_depth', From pedronis at codespeak.net Thu Dec 14 02:21:14 2006 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Thu, 14 Dec 2006 02:21:14 +0100 (CET) Subject: [pypy-svn] r35717 - in pypy/dist/pypy: objspace/flow rpython rpython/test translator/c/test Message-ID: <20061214012114.E8DED10075@code0.codespeak.net> Author: pedronis Date: Thu Dec 14 02:21:11 2006 New Revision: 35717 Modified: pypy/dist/pypy/objspace/flow/objspace.py pypy/dist/pypy/rpython/annlowlevel.py pypy/dist/pypy/rpython/rstr.py pypy/dist/pypy/rpython/test/test_rstr.py pypy/dist/pypy/translator/c/test/test_typed.py Log: support for float(string) for RPython: rtyping, and translator/c (this is using break_up_float, parts_to_float, and a special helper to lift a ll string back to high-level to be able to use the former functions) To-do: for OO support there's the choice to implement the primitive parts_to_float, or override the string LLHelpers.ll_float. Modified: pypy/dist/pypy/objspace/flow/objspace.py ============================================================================== --- pypy/dist/pypy/objspace/flow/objspace.py (original) +++ pypy/dist/pypy/objspace/flow/objspace.py Thu Dec 14 02:21:11 2006 @@ -498,6 +498,7 @@ implicit_exceptions = { int: [ValueError], # built-ins that can always raise exceptions + float: [ValueError], chr: [ValueError], unichr: [ValueError], # specifying IndexError, and KeyError beyond Exception, Modified: pypy/dist/pypy/rpython/annlowlevel.py ============================================================================== --- pypy/dist/pypy/rpython/annlowlevel.py (original) +++ pypy/dist/pypy/rpython/annlowlevel.py Thu Dec 14 02:21:11 2006 @@ -342,6 +342,27 @@ # ____________________________________________________________ +def hlstr(ll_s): + if hasattr(ll_s, 'items'): + return ''.join(items) + else: + return ll_s._str + +class HLStrEntry(extregistry.ExtRegistryEntry): + _about_ = hlstr + + def compute_result_annotation(self, s_ll_str): + return annmodel.SomeString() + + def specialize_call(self, hop): + hop.exception_cannot_occur() + assert hop.args_r[0].lowleveltype == hop.r_result.lowleveltype + v_ll_str, = hop.inputargs(*hop.args_r) + return hop.genop('same_as', [v_ll_str], + resulttype = hop.r_result.lowleveltype) + +# ____________________________________________________________ + def cast_object_to_ptr(PTR, object): raise NotImplementedError("cast_object_to_ptr") Modified: pypy/dist/pypy/rpython/rstr.py ============================================================================== --- pypy/dist/pypy/rpython/rstr.py (original) +++ pypy/dist/pypy/rpython/rstr.py Thu Dec 14 02:21:11 2006 @@ -224,6 +224,13 @@ hop.exception_is_here() return hop.gendirectcall(self.ll.ll_int, v_str, v_base) + def rtype_float(self, hop): + hop.has_implicit_exception(ValueError) # record that we know about it + string_repr = hop.rtyper.type_system.rstr.string_repr + v_str, = hop.inputargs(string_repr) + hop.exception_is_here() + return hop.gendirectcall(self.ll.ll_float, v_str) + def ll_str(self, s): return s @@ -598,3 +605,31 @@ if curstr: r.append(curstr) return r + + def ll_float(ll_str): + from pypy.rpython.annlowlevel import hlstr + from pypy.rlib.rarithmetic import break_up_float, parts_to_float + s = hlstr(ll_str) + + n = len(s) + beg = 0 + while beg < n: + if s[beg] == ' ': + beg += 1 + else: + break + if beg == n: + raise ValueError + end = n-1 + while end >= 0: + if s[end] == ' ': + end -= 1 + else: + break + assert end >= 0 + sign, before_point, after_point, exponent = break_up_float(s[beg:end+1]) + + if not before_point and not after_point: + raise ValueError + + return parts_to_float(sign, before_point, after_point, exponent) Modified: pypy/dist/pypy/rpython/test/test_rstr.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_rstr.py (original) +++ pypy/dist/pypy/rpython/test/test_rstr.py Thu Dec 14 02:21:11 2006 @@ -2,6 +2,7 @@ from pypy.rpython.lltypesystem.lltype import * from pypy.rpython.rstr import AbstractLLHelpers from pypy.rpython.lltypesystem.rstr import LLHelpers, mallocstr +from pypy.rpython.ootypesystem.ootype import make_string from pypy.rpython.rtyper import RPythonTyper, TyperError from pypy.rpython.test.tool import BaseRtypingTest, LLRtypeMixin, OORtypeMixin from pypy.rpython.llinterp import LLException @@ -571,6 +572,21 @@ res = self.interpret(fn, [1]) assert res == -654 + def test_float(self): + f = ['', ' ', '0', '1', '-1.5', '1.5E2', '2.5e-1', ' 0 ', '?'] + def fn(i): + s = f[i] + return float(s) + + for i in range(len(f)): + try: + expected = fn(i) + except ValueError: + self.interpret_raises(ValueError, fn, [i]) + else: + res = self.interpret(fn, [i]) + assert res == expected + def test_char_mul_n(self): def f(c, n): return c*n @@ -628,6 +644,15 @@ res = self.interpret(fn, []) assert res == 1 + def test_hlstr(self): + from pypy.rpython.annlowlevel import hlstr + def f(s): + return "*"+hlstr(s)+"*" == "*abba*" + + res = self.interpret(f, [self.string_to_ll("abba")]) + assert res + + def FIXME_test_str_to_pystringobj(): def f(n): if n >= 0: @@ -649,24 +674,21 @@ EMPTY_STRING_HASH = -1 - def llstr(self, s): - p = mallocstr(len(s)) - for i in range(len(s)): - p.chars[i] = s[i] - return p - def test_ll_find_rfind(self): + llstr = self.string_to_ll + for i in range(50): n1 = random.randint(0, 10) s1 = ''.join([random.choice("ab") for i in range(n1)]) n2 = random.randint(0, 5) s2 = ''.join([random.choice("ab") for i in range(n2)]) - res = LLHelpers.ll_find(self.llstr(s1), self.llstr(s2), 0, n1) + res = LLHelpers.ll_find(llstr(s1), llstr(s2), 0, n1) assert res == s1.find(s2) - res = LLHelpers.ll_rfind(self.llstr(s1), self.llstr(s2), 0, n1) + res = LLHelpers.ll_rfind(llstr(s1), llstr(s2), 0, n1) assert res == s1.rfind(s2) class TestOOtype(BaseTestRstr, OORtypeMixin): EMPTY_STRING_HASH = 0 + Modified: pypy/dist/pypy/translator/c/test/test_typed.py ============================================================================== --- pypy/dist/pypy/translator/c/test/test_typed.py (original) +++ pypy/dist/pypy/translator/c/test/test_typed.py Thu Dec 14 02:21:11 2006 @@ -753,3 +753,20 @@ fn = self.getcompiled(f) res = fn() assert res == 42 + + def test_float(self): + ex = ['', ' ', '0', '1', '-1.5', '1.5E2', '2.5e-1', ' 0 ', '?'] + def f(i): + s = ex[i] + try: + return float(s) + except ValueError: + return -999.0 + + fn = self.getcompiled(f, [int]) + + for i in range(len(ex)): + expected = f(i) + res = fn(i) + assert res == expected + From arigo at codespeak.net Thu Dec 14 07:24:19 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 14 Dec 2006 07:24:19 +0100 (CET) Subject: [pypy-svn] r35719 - in pypy/dist/pypy/module/_stackless: . test Message-ID: <20061214062419.DBD1B10071@code0.codespeak.net> Author: arigo Date: Thu Dec 14 07:24:16 2006 New Revision: 35719 Modified: pypy/dist/pypy/module/_stackless/coroutine.py pypy/dist/pypy/module/_stackless/interp_coroutine.py pypy/dist/pypy/module/_stackless/interp_greenlet.py pypy/dist/pypy/module/_stackless/test/test_greenlet.py Log: A serious attempt at completing interp_greenlet. It involved fixing the parent logic used when Coroutine delegates to py.magic.greenlets, i.e. on top of CPython. Doing the Right Thing about parents is kind of easy with greenlets when nothing else is around, but it's more fun to deal with when they interact with other pieces of code that have their own dynamic idea about what the parent should be. Ported all the py lib greenlet tests. Only one failure (skipped for now) about a gc.collect() that should trigger a GreenletExit but doesn't - to investigate. Modified: pypy/dist/pypy/module/_stackless/coroutine.py ============================================================================== --- pypy/dist/pypy/module/_stackless/coroutine.py (original) +++ pypy/dist/pypy/module/_stackless/coroutine.py Thu Dec 14 07:24:16 2006 @@ -123,7 +123,7 @@ if self.get_is_zombie(): return self.set_is_zombie(True) - self.space.userdel(self) + self.space.userdel(self.space.wrap(self)) def w_getcurrent(space): return space.wrap(AppCoroutine._get_state(space).current) Modified: pypy/dist/pypy/module/_stackless/interp_coroutine.py ============================================================================== --- pypy/dist/pypy/module/_stackless/interp_coroutine.py (original) +++ pypy/dist/pypy/module/_stackless/interp_coroutine.py Thu Dec 14 07:24:16 2006 @@ -35,12 +35,13 @@ try: from py.magic import greenlet - #main_greenlet = greenlet.getcurrent() + main_greenlet = greenlet.getcurrent() except (ImportError, ValueError): def greenlet(*args, **kwargs): raise NotImplementedError("need either greenlets or a translated version of pypy") class FrameChain(object): + """Greenlet-based emulation of the primitive rstack 'frames' of RPython""" def __init__(self, thunk=None): if thunk: @@ -52,11 +53,6 @@ last = FrameChain() return self.greenlet.switch(last) - def shutdown(self): - current = FrameChain() - target = current.greenlet.parent - target.switch(None) - import sys, os @@ -111,6 +107,10 @@ if self.things_to_do: self._do_things_to_do() + def push_exception(self, exc): + self.things_to_do = True + self.temp_exc = exc + def check_for_zombie(self, obj): return co in self.to_delete @@ -188,22 +188,25 @@ self.frame = self._greenlet_bind() def _greenlet_bind(self): - state = self.costate - self.parent = state.current - assert self.parent is not None weak = [self] def _greenlet_execute(incoming_frame): try: - return weak[0]._execute(incoming_frame) - finally: - del weak[0] - chain.shutdown() + chain2go2next = weak[0]._execute(incoming_frame) + except: + # no exception is supposed to get out of _execute() + # better report it directly into the main greenlet then, + # and hidden to prevent catching + main_greenlet.throw(AssertionError( + "unexpected exception out of Coroutine._execute()", + *sys.exc_info())) + assert 0 + del weak[0] + greenlet.getcurrent().parent = chain2go2next.greenlet + return None # as the result of the FrameChain.switch() chain = FrameChain(_greenlet_execute) return chain def _bind(self): - state = self.costate - self.parent = state.current incoming_frame = yield_current_frame_to_caller() return self._execute(incoming_frame) @@ -213,9 +216,9 @@ try: try: exc = None - syncstate.switched(incoming_frame) thunk = self.thunk self.thunk = None + syncstate.switched(incoming_frame) thunk.call() resume_point("coroutine__bind", state) except Exception, e: @@ -232,8 +235,7 @@ pass except Exception, e: # redirect all unhandled exceptions to the parent - syncstate.things_to_do = True - syncstate.temp_exc = exc + syncstate.push_exception(e) while self.parent is not None and self.parent.frame is None: # greenlet behavior is fine self.parent = self.parent.parent @@ -253,9 +255,21 @@ if self.frame is None: return state = self.costate - syncstate.things_to_do = True - syncstate.temp_exc = CoroutineExit() - self.parent = state.current + syncstate.push_exception(CoroutineExit()) + # careful here - if setting self.parent to state.current would + # create a loop, break it. The assumption is that 'self' + # will die, so that state.current's chain of parents can be + # modified to skip 'self' without too many people noticing. + p = state.current + if p is self or self.parent is None: + pass # killing the current of the main - don't change any parent + else: + while p.parent is not None: + if p.parent is self: + p.parent = self.parent + break + p = p.parent + self.parent = state.current self.switch() def _kill_finally(self): Modified: pypy/dist/pypy/module/_stackless/interp_greenlet.py ============================================================================== --- pypy/dist/pypy/module/_stackless/interp_greenlet.py (original) +++ pypy/dist/pypy/module/_stackless/interp_greenlet.py Thu Dec 14 07:24:16 2006 @@ -1,155 +1,199 @@ -from pypy.interpreter.baseobjspace import Wrappable from pypy.interpreter.argument import Arguments from pypy.interpreter.typedef import GetSetProperty, TypeDef -from pypy.interpreter.typedef import interp_attrproperty, interp_attrproperty_w from pypy.interpreter.gateway import interp2app, ObjSpace, W_Root +from pypy.interpreter.gateway import NoneNotWrapped from pypy.interpreter.error import OperationError -from pypy.interpreter.function import StaticMethod -from pypy.module._stackless.stackless_flags import StacklessFlags -from pypy.module._stackless.interp_coroutine import Coroutine, BaseCoState, AbstractThunk -from pypy.module._stackless.coroutine import _AppThunk, makeStaticMethod +from pypy.module._stackless.interp_coroutine import Coroutine, BaseCoState +from pypy.module._stackless.interp_coroutine import AbstractThunk, syncstate +from pypy.module._stackless.coroutine import makeStaticMethod + class GreenletThunk(AbstractThunk): - def __init__(self, space, costate, greenlet): - self.space = space - self.costate = costate + def __init__(self, greenlet): self.greenlet = greenlet def call(self): - __args__ = self.costate.__args__ - assert __args__ is not None + greenlet = self.greenlet + greenlet.active = True try: - w_result = self.space.call_args(self.greenlet.w_callable, __args__) - except OperationError, operr: - self.greenlet.w_dead = self.space.w_True - self.costate.operr = operr - w_result = self.space.w_None - else: - self.greenlet.w_dead = self.space.w_True - while 1: - __args__ = Arguments(self.space, [w_result]) + space = greenlet.space + args_w = greenlet.costate.args_w + __args__ = Arguments(space, args_w) try: - w_result = self.greenlet.w_parent.w_switch(__args__) - except OperationError, operr: - self.costate.operr = operr + w_run = space.getattr(space.wrap(greenlet), space.wrap('run')) + greenlet.w_callable = None + w_result = space.call_args(w_run, __args__) + except OperationError, operror: + if not operror.match(space, greenlet.costate.w_GreenletExit): + raise + w_result = operror.w_value + finally: + greenlet.active = False + greenlet.costate.args_w = [w_result] class AppGreenletCoState(BaseCoState): def __init__(self, space): BaseCoState.__init__(self) - self.__args__ = None + self.args_w = None self.space = space - self.operr = None - + self.w_GreenletExit = get(space, "GreenletExit") + self.w_GreenletError = get(space, "GreenletError") + def post_install(self): self.current = self.main = AppGreenlet(self.space, is_main=True) class AppGreenlet(Coroutine): def __init__(self, space, w_callable=None, is_main=False): + Coroutine.__init__(self, self._get_state(space)) self.space = space self.w_callable = w_callable - self.w_dead = space.w_False - self.has_ever_run = False or is_main - self.is_main = is_main - state = self._get_state(space) - if is_main: - self.w_parent = None - else: - w_parent = state.current - assert isinstance(w_parent, AppGreenlet) - self.w_parent = w_parent - Coroutine.__init__(self, state) + self.active = is_main self.subctx = space.getexecutioncontext().Subcontext() if is_main: self.subctx.framestack = None # wack else: - self.bind(GreenletThunk(space, state, self)) + self.bind(GreenletThunk(self)) - def descr_method__new__(space, w_subtype, w_callable): + def descr_method__new__(space, w_subtype, __args__): co = space.allocate_instance(AppGreenlet, w_subtype) - AppGreenlet.__init__(co, space, w_callable) + AppGreenlet.__init__(co, space) return space.wrap(co) + def descr_method__init__(self, w_run=NoneNotWrapped, + w_parent=NoneNotWrapped): + if w_run is not None: + self.w_set_run.im_func(self.space, self, w_run) + if w_parent is not None: + self.w_set_parent.im_func(self.space, self, w_parent) + # XXX strange style above, GetSetProperty needs a cleanup + def _get_state(space): return space.fromcache(AppGreenletCoState) _get_state = staticmethod(_get_state) def hello(self): + print "hello ", id(self), self.subctx.framestack.items + print syncstate.things_to_do, syncstate.temp_exc ec = self.space.getexecutioncontext() self.subctx.enter(ec) def goodbye(self): ec = self.space.getexecutioncontext() self.subctx.leave(ec) + print "goodbye", id(self), self.subctx.framestack.items + print syncstate.things_to_do, syncstate.temp_exc def w_getcurrent(space): return space.wrap(AppGreenlet._get_state(space).current) w_getcurrent = staticmethod(w_getcurrent) - def w_switch(self, __args__): - #print "switch", __args__, id(self) - if __args__.num_kwds(): - raise OperationError( - self.space.w_TypeError, - self.space.wrap("switch() takes not keyword arguments")) - self.has_ever_run = True - self.costate.__args__ = __args__ - self.switch() - #print "after switch" - #print self.costate.__args__ - if self.costate.operr is not None: - operr = self.costate.operr - self.costate.operr = None - raise operr - args_w, kwds_w = self.costate.__args__.unpack() - if len(args_w) == 1: - return args_w[0] - return self.space.newtuple(args_w) - - def w_throw(self, w_exception): - self.costate.operr = OperationError(w_exception, self.space.wrap("")) - self.w_switch(Arguments(self.space, [])) + def w_switch(self, args_w): + # Find the switch target - it might be a parent greenlet + space = self.space + costate = self.costate + target = self + while target.isdead(): + target = target.parent + assert isinstance(target, AppGreenlet) + # Switch to it + costate.args_w = args_w + if target is not costate.current: + target.switch() + else: + # case not handled in Coroutine.switch() + syncstate._do_things_to_do() + result_w = costate.args_w + costate.args_w = None + # costate.args_w can be set to None above for throw(), but then + # switch() should have raised. At this point cosstate.args_w != None. + assert result_w is not None + # Return the result of a switch, packaging it in a tuple if + # there is more than one value. + if len(result_w) == 1: + return result_w[0] + return space.newtuple(result_w) + + def w_throw(self, w_type=None, w_value=None, w_traceback=None): + space = self.space + if space.is_w(w_type, space.w_None): + w_type = self.costate.w_GreenletExit + # Code copied from RAISE_VARARGS but slightly modified. Not too nice. + operror = OperationError(w_type, w_value) + operror.normalize_exception(space) + if not space.is_w(w_traceback, space.w_None): + from pypy.interpreter import pytraceback + tb = space.interpclass_w(w_traceback) + if tb is None or not space.is_true(space.isinstance(tb, + space.gettypeobject(pytraceback.PyTraceback.typedef))): + raise OperationError(space.w_TypeError, + space.wrap("throw: arg 3 must be a traceback or None")) + operror.application_traceback = tb + # Dead greenlet: turn GreenletExit into a regular return + if self.isdead() and operror.match(space, self.costate.w_GreenletExit): + args_w = [operror.w_value] + else: + syncstate.push_exception(operror) + args_w = None + return self.w_switch(args_w) def _userdel(self): - self.space.userdel(self) + self.space.userdel(self.space.wrap(self)) -def w_get_is_dead(space, w_self): - self = space.interp_w(AppGreenlet, w_self) - return self.w_dead - -def descr__bool__(space, w_self): - self = space.interp_w(AppGreenlet, w_self) - return space.wrap(self.has_ever_run and not space.is_true(self.w_dead)) - -def w_get_parent(space, w_self): - self = space.interp_w(AppGreenlet, w_self) - if self.w_parent is not None: - return self.w_parent - else: - return space.w_None - -def w_set_parent(space, w_self, w_parent): - self = space.interp_w(AppGreenlet, w_self) - newparent = space.interp_w(AppGreenlet, w_parent) - curr = newparent - while 1: - if space.is_true(space.is_(self, curr)): - raise OperationError(space.w_ValueError, space.wrap("cyclic parent chain")) - if not curr.w_parent is None: - break - curr = curr.w_parent - self.w_parent = newparent - -def w_get_frame(space, w_self): - self = space.interp_w(AppGreenlet, w_self) - if (not self.has_ever_run or space.is_true(self.w_dead) or - self.costate.current is self): - return space.w_None - try: - return self.subctx.framestack.top(0) - except IndexError: - return space.w_None + def isdead(self): + return self.thunk is None and not self.active + + def w_get_is_dead(space, self): + return space.newbool(self.isdead()) + + def descr__nonzero__(self): + return self.space.newbool(self.active) + + def w_get_run(space, self): + w_run = self.w_callable + if w_run is None: + raise OperationError(space.w_AttributeError, space.wrap("run")) + return w_run + + def w_set_run(space, self, w_run): + space = self.space + if self.thunk is None: + raise OperationError(space.w_AttributeError, + space.wrap("run cannot be set " + "after the start of the greenlet")) + self.w_callable = w_run + + def w_del_run(space, self): + if self.w_callable is None: + raise OperationError(space.w_AttributeError, space.wrap("run")) + self.w_callable = None + + def w_get_parent(space, self): + return space.wrap(self.parent) + + def w_set_parent(space, self, w_parent): + newparent = space.interp_w(AppGreenlet, w_parent) + if newparent.costate is not self.costate: + raise OperationError(self.costate.w_GreenletError, + space.wrap("invalid foreign parent")) + curr = newparent + while curr: + if curr is self: + raise OperationError(space.w_ValueError, + space.wrap("cyclic parent chain")) + curr = curr.parent + self.parent = newparent + + def w_get_frame(space, self): + if not self.active or self.costate.current is self: + f = None + else: + try: + f = self.subctx.framestack.top(0) + except IndexError: + f = None + return space.wrap(f) def get(space, name): w_module = space.getbuiltinmodule('_stackless') @@ -158,25 +202,32 @@ def post_install(module): makeStaticMethod(module, 'greenlet', 'getcurrent') space = module.space - AppGreenlet._get_state(space).post_install() + state = AppGreenlet._get_state(space) + state.post_install() w_module = space.getbuiltinmodule('_stackless') - space.appexec([w_module, get(space, "GreenletExit"), - get(space, "GreenletError")], """ + space.appexec([w_module, + state.w_GreenletExit, + state.w_GreenletError], """ (mod, exit, error): mod.greenlet.GreenletExit = exit mod.greenlet.error = error """) AppGreenlet.typedef = TypeDef("greenlet", - __new__ = interp2app(AppGreenlet.descr_method__new__.im_func), + __new__ = interp2app(AppGreenlet.descr_method__new__.im_func, + unwrap_spec=[ObjSpace, W_Root, Arguments]), + __init__ = interp2app(AppGreenlet.descr_method__init__), switch = interp2app(AppGreenlet.w_switch, - unwrap_spec=['self', Arguments]), - dead = GetSetProperty(w_get_is_dead), - parent = GetSetProperty(w_get_parent, w_set_parent), + unwrap_spec=['self', 'args_w']), + dead = GetSetProperty(AppGreenlet.w_get_is_dead), + run = GetSetProperty(AppGreenlet.w_get_run, + AppGreenlet.w_set_run, + AppGreenlet.w_del_run), + parent = GetSetProperty(AppGreenlet.w_get_parent, + AppGreenlet.w_set_parent), getcurrent = interp2app(AppGreenlet.w_getcurrent), throw = interp2app(AppGreenlet.w_throw), - gr_frame = GetSetProperty(w_get_frame), - __nonzero__ = interp2app(descr__bool__), + gr_frame = GetSetProperty(AppGreenlet.w_get_frame), + __nonzero__ = interp2app(AppGreenlet.descr__nonzero__), __module__ = '_stackless', ) - Modified: pypy/dist/pypy/module/_stackless/test/test_greenlet.py ============================================================================== --- pypy/dist/pypy/module/_stackless/test/test_greenlet.py (original) +++ pypy/dist/pypy/module/_stackless/test/test_greenlet.py Thu Dec 14 07:24:16 2006 @@ -1,6 +1,6 @@ from pypy.conftest import gettestobjspace, skip_on_missing_buildoption -class AppTest_Coroutine: +class AppTest_Greenlet: def setup_class(cls): space = gettestobjspace(usemodules=('_stackless',)) @@ -193,3 +193,434 @@ del g2 assert seen == [greenlet.GreenletExit, greenlet.GreenletExit] + +# ____________________________________________________________ +# +# The tests from py.magic.greenlet +# For now, without the ones that involve threads +# +class AppTest_PyMagicTestGreenlet: + + def setup_class(cls): + space = gettestobjspace(usemodules=('_stackless',)) + cls.space = space + cls.w_glob = space.appexec([], """(): + import sys + from _stackless import greenlet + + class SomeError(Exception): + pass + + def fmain(seen): + try: + greenlet.getcurrent().parent.switch() + except: + seen.append(sys.exc_info()[0]) + raise + raise SomeError + + class Glob: pass + glob = Glob() + glob.__dict__.update(locals()) + return glob + """) + + def test_simple(self): + greenlet = self.glob.greenlet + lst = [] + def f(): + lst.append(1) + greenlet.getcurrent().parent.switch() + lst.append(3) + g = greenlet(f) + lst.append(0) + g.switch() + lst.append(2) + g.switch() + lst.append(4) + assert lst == range(5) + + def test_exception(self): + greenlet = self.glob.greenlet + fmain = self.glob.fmain + SomeError = self.glob.SomeError + seen = [] + g1 = greenlet(fmain) + g2 = greenlet(fmain) + g1.switch(seen) + g2.switch(seen) + g2.parent = g1 + assert seen == [] + raises(SomeError, g2.switch) + assert seen == [SomeError] + g2.switch() + assert seen == [SomeError] + + def test_send_exception(self): + greenlet = self.glob.greenlet + fmain = self.glob.fmain + def send_exception(g, exc): + # note: send_exception(g, exc) can be now done with g.throw(exc). + # the purpose of this test is to explicitely check the + # propagation rules. + def crasher(exc): + raise exc + g1 = greenlet(crasher, parent=g) + g1.switch(exc) + + seen = [] + g1 = greenlet(fmain) + g1.switch(seen) + raises(KeyError, "send_exception(g1, KeyError)") + assert seen == [KeyError] + + def test_dealloc(self): + skip("XXX in-progress: GC handling of greenlets") + import gc + greenlet = self.glob.greenlet + fmain = self.glob.fmain + seen = [] + g1 = greenlet(fmain) + g2 = greenlet(fmain) + g1.switch(seen) + g2.switch(seen) + assert seen == [] + del g1 + gc.collect() + assert seen == [greenlet.GreenletExit] + del g2 + gc.collect() + assert seen == [greenlet.GreenletExit, greenlet.GreenletExit] + + def test_frame(self): + import sys + greenlet = self.glob.greenlet + def f1(): + f = sys._getframe(0) + assert f.f_back is None + greenlet.getcurrent().parent.switch(f) + return "meaning of life" + g = greenlet(f1) + frame = g.switch() + assert frame is g.gr_frame + assert g + next = g.switch() + assert not g + assert next == "meaning of life" + assert g.gr_frame is None + + +class AppTest_PyMagicTestThrow: + + def setup_class(cls): + space = gettestobjspace(usemodules=('_stackless',)) + cls.space = space + + def test_class(self): + from _stackless import greenlet + def switch(*args): + return greenlet.getcurrent().parent.switch(*args) + + def f(): + try: + switch("ok") + except RuntimeError: + switch("ok") + return + switch("fail") + + g = greenlet(f) + res = g.switch() + assert res == "ok" + res = g.throw(RuntimeError) + assert res == "ok" + + def test_val(self): + from _stackless import greenlet + def switch(*args): + return greenlet.getcurrent().parent.switch(*args) + + def f(): + try: + switch("ok") + except RuntimeError, val: + if str(val) == "ciao": + switch("ok") + return + switch("fail") + + g = greenlet(f) + res = g.switch() + assert res == "ok" + res = g.throw(RuntimeError("ciao")) + assert res == "ok" + + g = greenlet(f) + res = g.switch() + assert res == "ok" + res = g.throw(RuntimeError, "ciao") + assert res == "ok" + + def test_kill(self): + from _stackless import greenlet + def switch(*args): + return greenlet.getcurrent().parent.switch(*args) + + def f(): + switch("ok") + switch("fail") + + g = greenlet(f) + res = g.switch() + assert res == "ok" + res = g.throw() + assert isinstance(res, greenlet.GreenletExit) + assert g.dead + res = g.throw() # immediately eaten by the already-dead greenlet + assert isinstance(res, greenlet.GreenletExit) + + def test_throw_goes_to_original_parent(self): + from _stackless import greenlet + main = greenlet.getcurrent() + def f1(): + try: + main.switch("f1 ready to catch") + except IndexError: + return "caught" + else: + return "normal exit" + def f2(): + main.switch("from f2") + + g1 = greenlet(f1) + g2 = greenlet(f2, parent=g1) + raises(IndexError, g2.throw, IndexError) + assert g2.dead + assert g1.dead + + g1 = greenlet(f1) + g2 = greenlet(f2, parent=g1) + res = g1.switch() + assert res == "f1 ready to catch" + res = g2.throw(IndexError) + assert res == "caught" + assert g2.dead + assert g1.dead + + g1 = greenlet(f1) + g2 = greenlet(f2, parent=g1) + res = g1.switch() + assert res == "f1 ready to catch" + res = g2.switch() + assert res == "from f2" + res = g2.throw(IndexError) + assert res == "caught" + assert g2.dead + assert g1.dead + + +class AppTest_PyMagicTestGenerator: + + def setup_class(cls): + space = gettestobjspace(usemodules=('_stackless',)) + cls.space = space + + def test_generator(self): + from _stackless import greenlet + + class genlet(greenlet): + + def __init__(self, *args, **kwds): + self.args = args + self.kwds = kwds + + def run(self): + fn, = self.fn + fn(*self.args, **self.kwds) + + def __iter__(self): + return self + + def next(self): + self.parent = greenlet.getcurrent() + result = self.switch() + if self: + return result + else: + raise StopIteration + + def Yield(value): + g = greenlet.getcurrent() + while not isinstance(g, genlet): + if g is None: + raise RuntimeError, 'yield outside a genlet' + g = g.parent + g.parent.switch(value) + + def generator(func): + class generator(genlet): + fn = (func,) + return generator + + # ___ test starts here ___ + seen = [] + def g(n): + for i in range(n): + seen.append(i) + Yield(i) + g = generator(g) + for k in range(3): + for j in g(5): + seen.append(j) + assert seen == 3 * [0, 0, 1, 1, 2, 2, 3, 3, 4, 4] + + +class AppTest_PyMagicTestGeneratorNested: + + def setup_class(cls): + space = gettestobjspace(usemodules=('_stackless',)) + cls.space = space + cls.w_glob = space.appexec([], """(): + from _stackless import greenlet + + class genlet(greenlet): + + def __init__(self, *args, **kwds): + self.args = args + self.kwds = kwds + self.child = None + + def run(self): + fn, = self.fn + fn(*self.args, **self.kwds) + + def __iter__(self): + return self + + def set_child(self, child): + self.child = child + + def next(self): + if self.child: + child = self.child + while child.child: + tmp = child + child = child.child + tmp.child = None + + result = child.switch() + else: + self.parent = greenlet.getcurrent() + result = self.switch() + + if self: + return result + else: + raise StopIteration + + def Yield(value, level = 1): + g = greenlet.getcurrent() + + while level != 0: + if not isinstance(g, genlet): + raise RuntimeError, 'yield outside a genlet' + if level > 1: + g.parent.set_child(g) + g = g.parent + level -= 1 + + g.switch(value) + + def Genlet(func): + class Genlet(genlet): + fn = (func,) + return Genlet + + class Glob: pass + glob = Glob() + glob.__dict__.update(locals()) + return glob + """) + + def test_genlet_1(self): + Genlet = self.glob.Genlet + Yield = self.glob.Yield + + def g1(n, seen): + for i in range(n): + seen.append(i+1) + yield i + + def g2(n, seen): + for i in range(n): + seen.append(i+1) + Yield(i) + + g2 = Genlet(g2) + + def nested(i): + Yield(i) + + def g3(n, seen): + for i in range(n): + seen.append(i+1) + nested(i) + g3 = Genlet(g3) + + raises(RuntimeError, Yield, 10) + for g in [g1, g2, g3]: + seen = [] + for k in range(3): + for j in g(5, seen): + seen.append(j) + assert seen == 3 * [1, 0, 2, 1, 3, 2, 4, 3, 5, 4] + raises(RuntimeError, Yield, 10) + + def test_nested_genlets(self): + Genlet = self.glob.Genlet + Yield = self.glob.Yield + def a(n): + if n == 0: + return + for ii in ax(n-1): + Yield(ii) + Yield(n) + ax = Genlet(a) + seen = [] + for ii in ax(5): + seen.append(ii) + assert seen == [1, 2, 3, 4, 5] + + def test_perms(self): + Genlet = self.glob.Genlet + Yield = self.glob.Yield + def perms(l): + if len(l) > 1: + for e in l: + # No syntactical sugar for generator expressions + [Yield([e] + p) for p in perms([x for x in l if x!=e])] + else: + Yield(l) + perms = Genlet(perms) + gen_perms = perms(range(4)) + permutations = list(gen_perms) + assert len(permutations) == 4*3*2*1 + assert [0,1,2,3] in permutations + assert [3,2,1,0] in permutations + + def test_layered_genlets(self): + Genlet = self.glob.Genlet + Yield = self.glob.Yield + def gr1(n): + for ii in range(1, n): + Yield(ii) + Yield(ii * ii, 2) + gr1 = Genlet(gr1) + def gr2(n, seen): + for ii in gr1(n): + seen.append(ii) + gr2 = Genlet(gr2) + seen = [] + for ii in gr2(5, seen): + seen.append(ii) + assert seen == [1, 1, 2, 4, 3, 9, 4, 16] From arigo at codespeak.net Thu Dec 14 07:31:18 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 14 Dec 2006 07:31:18 +0100 (CET) Subject: [pypy-svn] r35720 - pypy/dist/pypy/lib Message-ID: <20061214063118.2028310071@code0.codespeak.net> Author: arigo Date: Thu Dec 14 07:31:17 2006 New Revision: 35720 Added: pypy/dist/pypy/lib/stackless.py - copied unchanged from r35688, pypy/dist/pypy/lib/stackless.py pypy/dist/pypy/lib/stackless_new.py - copied unchanged from r35719, pypy/dist/pypy/lib/stackless.py Removed: pypy/dist/pypy/lib/stackless_old.py Log: Temporarily keep the old stackless.py. The new one seems to break all tests depending on it (at least its own test_stackless, and test_distributed). Stephan: I suspect that you only tested it on top of CPython with your greenlet-based wrapper (could you check it in somewhere too, btw?). The behavior of this wrapper probably differs from the behavior of the module/_stackless coroutine in some way. From arigo at codespeak.net Thu Dec 14 09:01:42 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 14 Dec 2006 09:01:42 +0100 (CET) Subject: [pypy-svn] r35721 - pypy/dist/pypy/doc Message-ID: <20061214080142.D3FBC10071@code0.codespeak.net> Author: arigo Date: Thu Dec 14 09:01:40 2006 New Revision: 35721 Modified: pypy/dist/pypy/doc/getting-started.txt pypy/dist/pypy/doc/index.txt Log: issue138 resolved Listing platforms where PyPy runs. Modified: pypy/dist/pypy/doc/getting-started.txt ============================================================================== --- pypy/dist/pypy/doc/getting-started.txt (original) +++ pypy/dist/pypy/doc/getting-started.txt Thu Dec 14 09:01:40 2006 @@ -106,7 +106,7 @@ Running all of PyPy's tests --------------------------- -If you want to see if PyPy works on your machine/platform +If you want to see `if PyPy works on your machine/platform`_ you can simply run PyPy's large test suite with:: cd pypy @@ -115,6 +115,8 @@ test_all.py is just another name for `py.test`_ which is the testing tool that we are using and enhancing for PyPy. +.. _`if PyPy works on your machine/platform`: index.html#status + Filing bugs or feature requests ------------------------------- Modified: pypy/dist/pypy/doc/index.txt ============================================================================== --- pypy/dist/pypy/doc/index.txt (original) +++ pypy/dist/pypy/doc/index.txt Thu Dec 14 09:01:40 2006 @@ -111,6 +111,16 @@ Status ====================================== +PyPy is mainly developed on Linux and Mac OS/X. Windows is supported, +but platform-specific bugs tend to take longer before we notice and fix +them. About 64-bit machines: although support is mostly present, we +decided to stop tracking and fixing the remaining issues for a while, as +an attempt to keep some focus. So PyPy requires a 32-bit machine or OS +for now. + +*Some links below are broken because of hardware failure of the +snake server - PyPy kills machines :-)* + PyPy's own tests, daily updated, `on Linux`_ and `on Windows`_ and on `build pypy-c`_ (various variants). From arigo at codespeak.net Thu Dec 14 10:07:17 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 14 Dec 2006 10:07:17 +0100 (CET) Subject: [pypy-svn] r35722 - in pypy/dist/pypy/rpython: . lltypesystem test Message-ID: <20061214090717.F3A1A10071@code0.codespeak.net> Author: arigo Date: Thu Dec 14 10:07:15 2006 New Revision: 35722 Added: pypy/dist/pypy/rpython/rcontrollerentry.py (contents, props changed) pypy/dist/pypy/rpython/test/test_controllerentry.py (contents, props changed) Modified: pypy/dist/pypy/rpython/controllerentry.py pypy/dist/pypy/rpython/lltypesystem/rpbc.py pypy/dist/pypy/rpython/rtyper.py Log: (pedronis around, arigo) RTyping for controllerentry. Modified: pypy/dist/pypy/rpython/controllerentry.py ============================================================================== --- pypy/dist/pypy/rpython/controllerentry.py (original) +++ pypy/dist/pypy/rpython/controllerentry.py Thu Dec 14 10:07:15 2006 @@ -16,6 +16,10 @@ def getcontroller(self, *args_s): return self._controller_() + def specialize_call(self, hop): + controller = hop.s_result.controller + return controller.rtype_new(hop) + class Controller(object): __metaclass__ = cachedtype @@ -26,6 +30,12 @@ def ctrl_new(self, *args_s): return delegate(self.new, *args_s) + def rtype_new(self, hop): + r_controlled_instance = hop.r_result + return r_controlled_instance.rtypedelegate(self.new, hop, + revealargs=[], + revealresult=True) + def ctrl_getattr(self, s_obj, s_attr): return delegate(self.getattr, s_obj, s_attr) @@ -33,9 +43,25 @@ return getattr(self, 'get_' + attr)(obj) getattr._annspecialcase_ = 'specialize:arg(2)' + def rtype_getattr(self, hop): + hop2 = hop.copy() + r_controlled_instance = hop2.args_r[0] + _, s_attr = hop2.r_s_pop(1) + attr = s_attr.const + getter = getattr(self, 'get_' + attr) + return r_controlled_instance.rtypedelegate(getter, hop2) + def ctrl_setattr(self, s_obj, s_attr, s_value): return delegate(self.setattr, s_obj, s_attr, s_value) + def rtype_setattr(self, hop): + hop2 = hop.copy() + r_controlled_instance = hop2.args_r[0] + _, s_attr = hop2.r_s_pop(1) + attr = s_attr.const + setter = getattr(self, 'set_' + attr) + return r_controlled_instance.rtypedelegate(setter, hop2) + def setattr(self, obj, attr, value): return getattr(self, 'set_' + attr)(obj, value) setattr._annspecialcase_ = 'specialize:arg(2)' @@ -56,6 +82,14 @@ self.controller = controller self.knowntype = controller.knowntype + def rtyper_makerepr(self, rtyper): + from pypy.rpython.rcontrollerentry import ControlledInstanceRepr + return ControlledInstanceRepr(rtyper, self.s_real_obj, self.controller) + + def rtyper_makekey_ex(self, rtyper): + real_key = rtyper.makekey(self.s_real_obj) + return self.__class__, real_key, self.controller + class __extend__(SomeControlledInstance): Modified: pypy/dist/pypy/rpython/lltypesystem/rpbc.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/rpbc.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/rpbc.py Thu Dec 14 10:07:15 2006 @@ -323,6 +323,7 @@ opname = 'simple_call' if call_args: opname = 'call_args' + hop2.forced_opname = opname hop2.v_s_insertfirstarg(v_func, s_func) # insert 'function' @@ -332,7 +333,7 @@ hop2.args_v[0] = hop2.llops.convertvar(hop2.args_v[0], r_func, hop2.args_r[0]) # now hop2 looks like simple_call(function, self, args...) - return hop2.dispatch(opname=opname) + return hop2.dispatch() # ____________________________________________________________ Added: pypy/dist/pypy/rpython/rcontrollerentry.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/rpython/rcontrollerentry.py Thu Dec 14 10:07:15 2006 @@ -0,0 +1,39 @@ +from pypy.objspace.flow.model import Constant +from pypy.rpython.rmodel import Repr +from pypy.rpython.error import TyperError + + +class ControlledInstanceRepr(Repr): + + def __init__(self, rtyper, s_real_obj, controller): + self.rtyper = rtyper + self.s_real_obj = s_real_obj + self.r_real_obj = rtyper.getrepr(s_real_obj) + self.controller = controller + self.lowleveltype = self.r_real_obj.lowleveltype + + def rtypedelegate(self, boundmethod, hop, + revealargs=[0], revealresult=False): + bk = self.rtyper.annotator.bookkeeper + c_meth = Constant(boundmethod) + s_meth = bk.immutablevalue(boundmethod) + hop2 = hop.copy() + for index in revealargs: + s_new, r_new = self.reveal(hop2.args_r[index]) + hop2.args_s[index], hop2.args_r[index] = s_new, r_new + if revealresult: + hop2.s_result, hop2.r_result = self.reveal(hop2.r_result) + hop2.v_s_insertfirstarg(c_meth, s_meth) + hop2.forced_opname = 'simple_call' + return hop2.dispatch() + + def reveal(self, r): + if r is not self: + raise TyperError("expected %r, got %r" % (self, r)) + return self.s_real_obj, self.r_real_obj + + def rtype_getattr(self, hop): + return self.controller.rtype_getattr(hop) + + def rtype_setattr(self, hop): + return self.controller.rtype_setattr(hop) Modified: pypy/dist/pypy/rpython/rtyper.py ============================================================================== --- pypy/dist/pypy/rpython/rtyper.py (original) +++ pypy/dist/pypy/rpython/rtyper.py Thu Dec 14 10:07:15 2006 @@ -644,6 +644,7 @@ class HighLevelOp(object): + forced_opname = None def __init__(self, rtyper, spaceop, exceptionlinks, llops): self.rtyper = rtyper @@ -669,17 +670,17 @@ if type(value) is list: # grunt value = value[:] setattr(result, key, value) + result.forced_opname = self.forced_opname return result - def dispatch(self, opname=None): + def dispatch(self): rtyper = self.rtyper generic = rtyper.generic_translate_operation if generic is not None: res = generic(self) if res is not None: return res - if not opname: - opname = self.spaceop.opname + opname = self.forced_opname or self.spaceop.opname translate_meth = getattr(rtyper, 'translate_op_'+opname, rtyper.default_translate_operation) return translate_meth(self) Added: pypy/dist/pypy/rpython/test/test_controllerentry.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/rpython/test/test_controllerentry.py Thu Dec 14 10:07:15 2006 @@ -0,0 +1,41 @@ +from pypy.rpython.controllerentry import Controller, ControllerEntry + +from pypy.annotation.annrpython import RPythonAnnotator +from pypy.rpython.test.test_llinterp import interpret + + +class C: + "Imagine some magic here to have a foo attribute on instances" + +def fun(a): + lst = [] + c = C(a) + c.foo = lst # side-effect on lst! well, it's a test + return c.foo, lst[0] + +class C_Controller(Controller): + knowntype = C + + def new(self, a): + return a + '_' + + def get_foo(self, obj): + return obj + "2" + + def set_foo(self, obj, value): + value.append(obj) + +class Entry(ControllerEntry): + _about_ = C + _controller_ = C_Controller + + +def test_C_annotate(): + a = RPythonAnnotator() + s = a.build_types(fun, [a.bookkeeper.immutablevalue("4")]) + assert s.const == ("4_2", "4_") + +def test_C_specialize(): + res = interpret(fun, ["4"]) + assert ''.join(res.item0.chars) == "4_2" + assert ''.join(res.item1.chars) == "4_" From arigo at codespeak.net Thu Dec 14 10:33:16 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 14 Dec 2006 10:33:16 +0100 (CET) Subject: [pypy-svn] r35723 - in pypy/dist/pypy: annotation/test rpython rpython/test Message-ID: <20061214093316.49AB010079@code0.codespeak.net> Author: arigo Date: Thu Dec 14 10:33:14 2006 New Revision: 35723 Modified: pypy/dist/pypy/annotation/test/test_annrpython.py pypy/dist/pypy/rpython/controllerentry.py pypy/dist/pypy/rpython/rcontrollerentry.py pypy/dist/pypy/rpython/test/test_controllerentry.py Log: (pedronis, arigo) Support for prebuilt "controlled instances". Simplifications. Modified: pypy/dist/pypy/annotation/test/test_annrpython.py ============================================================================== --- pypy/dist/pypy/annotation/test/test_annrpython.py (original) +++ pypy/dist/pypy/annotation/test/test_annrpython.py Thu Dec 14 10:33:14 2006 @@ -2424,39 +2424,6 @@ py.test.raises(NoSuchSlotError, a.build_types, fun, [int]) - def test_simple_controllerentry(self): - from pypy.rpython.controllerentry import Controller, ControllerEntry - - class C: - "Imagine some magic here to have a foo attribute on instances" - - def fun(): - lst = [] - c = C() - c.foo = lst # side-effect on lst! well, it's a test - return c.foo, lst[0] - - class C_Controller(Controller): - knowntype = C - - def new(self): - return "4" - - def get_foo(self, obj): - return obj + "2" - - def set_foo(self, obj, value): - value.append(obj) - - class Entry(ControllerEntry): - _about_ = C - _controller_ = C_Controller - - a = self.RPythonAnnotator(policy=policy.AnnotatorPolicy()) - s = a.build_types(fun, []) - assert s.const == ("42", "4") - - def test_float_cmp(self): def fun(x, y): return (x < y, Modified: pypy/dist/pypy/rpython/controllerentry.py ============================================================================== --- pypy/dist/pypy/rpython/controllerentry.py (original) +++ pypy/dist/pypy/rpython/controllerentry.py Thu Dec 14 10:33:14 2006 @@ -21,6 +21,18 @@ return controller.rtype_new(hop) +class ControllerEntryForPrebuilt(ExtRegistryEntry): + + def compute_annotation(self): + controller = self.getcontroller() + real_obj = controller.convert(self.instance) + s_real_obj = self.bookkeeper.immutablevalue(real_obj) + return SomeControlledInstance(s_real_obj, controller) + + def getcontroller(self): + return self._controller_() + + class Controller(object): __metaclass__ = cachedtype @@ -44,23 +56,15 @@ getattr._annspecialcase_ = 'specialize:arg(2)' def rtype_getattr(self, hop): - hop2 = hop.copy() - r_controlled_instance = hop2.args_r[0] - _, s_attr = hop2.r_s_pop(1) - attr = s_attr.const - getter = getattr(self, 'get_' + attr) - return r_controlled_instance.rtypedelegate(getter, hop2) + r_controlled_instance = hop.args_r[0] + return r_controlled_instance.rtypedelegate(self.getattr, hop) def ctrl_setattr(self, s_obj, s_attr, s_value): return delegate(self.setattr, s_obj, s_attr, s_value) def rtype_setattr(self, hop): - hop2 = hop.copy() - r_controlled_instance = hop2.args_r[0] - _, s_attr = hop2.r_s_pop(1) - attr = s_attr.const - setter = getattr(self, 'set_' + attr) - return r_controlled_instance.rtypedelegate(setter, hop2) + r_controlled_instance = hop.args_r[0] + return r_controlled_instance.rtypedelegate(self.setattr, hop) def setattr(self, obj, attr, value): return getattr(self, 'set_' + attr)(obj, value) Modified: pypy/dist/pypy/rpython/rcontrollerentry.py ============================================================================== --- pypy/dist/pypy/rpython/rcontrollerentry.py (original) +++ pypy/dist/pypy/rpython/rcontrollerentry.py Thu Dec 14 10:33:14 2006 @@ -12,6 +12,10 @@ self.controller = controller self.lowleveltype = self.r_real_obj.lowleveltype + def convert_const(self, value): + real_value = self.controller.convert(value) + return self.r_real_obj.convert_const(real_value) + def rtypedelegate(self, boundmethod, hop, revealargs=[0], revealresult=False): bk = self.rtyper.annotator.bookkeeper Modified: pypy/dist/pypy/rpython/test/test_controllerentry.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_controllerentry.py (original) +++ pypy/dist/pypy/rpython/test/test_controllerentry.py Thu Dec 14 10:33:14 2006 @@ -1,10 +1,11 @@ from pypy.rpython.controllerentry import Controller, ControllerEntry +from pypy.rpython.controllerentry import ControllerEntryForPrebuilt from pypy.annotation.annrpython import RPythonAnnotator from pypy.rpython.test.test_llinterp import interpret -class C: +class C(object): "Imagine some magic here to have a foo attribute on instances" def fun(a): @@ -19,6 +20,9 @@ def new(self, a): return a + '_' + def convert(self, c): + return str(c._bar) + def get_foo(self, obj): return obj + "2" @@ -29,6 +33,10 @@ _about_ = C _controller_ = C_Controller +class Entry(ControllerEntryForPrebuilt): + _type_ = C + _controller_ = C_Controller + def test_C_annotate(): a = RPythonAnnotator() @@ -39,3 +47,28 @@ res = interpret(fun, ["4"]) assert ''.join(res.item0.chars) == "4_2" assert ''.join(res.item1.chars) == "4_" + + +c2 = C() +c2._bar = 51 + +c3 = C() +c3._bar = 7654 + +def fun2(flag): + if flag: + c = c2 + else: + c = c3 + return c.foo + +def test_C2_annotate(): + a = RPythonAnnotator() + s = a.build_types(fun2, [a.bookkeeper.immutablevalue(True)]) + assert s.const == "512" + +def test_C2_specialize(): + res = interpret(fun2, [True]) + assert ''.join(res.chars) == "512" + res = interpret(fun2, [False]) + assert ''.join(res.chars) == "76542" From mwh at codespeak.net Thu Dec 14 10:33:32 2006 From: mwh at codespeak.net (mwh at codespeak.net) Date: Thu, 14 Dec 2006 10:33:32 +0100 (CET) Subject: [pypy-svn] r35724 - pypy/dist/pypy/doc Message-ID: <20061214093332.B374310079@code0.codespeak.net> Author: mwh Date: Thu Dec 14 10:33:29 2006 New Revision: 35724 Modified: pypy/dist/pypy/doc/index.txt Log: pedantry about the spelling of "Mac OS X" and link to the nightly benchmarks on tuatara. Modified: pypy/dist/pypy/doc/index.txt ============================================================================== --- pypy/dist/pypy/doc/index.txt (original) +++ pypy/dist/pypy/doc/index.txt Thu Dec 14 10:33:29 2006 @@ -111,7 +111,7 @@ Status ====================================== -PyPy is mainly developed on Linux and Mac OS/X. Windows is supported, +PyPy is mainly developed on Linux and Mac OS X. Windows is supported, but platform-specific bugs tend to take longer before we notice and fix them. About 64-bit machines: although support is mostly present, we decided to stop tracking and fixing the remaining issues for a while, as @@ -158,7 +158,7 @@ .. _`on Linux`: http://snake.cs.uni-duesseldorf.de/pypytest/summary.html .. _`on Windows`: http://scottdial.com/pypytest/summary.html .. _`ideas for PyPy related projects`: project-ideas.html -.. _`Nightly builds and benchmarks`: http://snake.cs.uni-duesseldorf.de/pypytest/benchmark.html +.. _`Nightly builds and benchmarks`: http://tuatara.cs.uni-duesseldorf.de/benchmark.html .. _`build pypy-c`: http://snake.cs.uni-duesseldorf.de/pypy-c-tests/ .. _`directory reference`: .. _`rlib`: rlib.html From mwh at codespeak.net Thu Dec 14 10:34:25 2006 From: mwh at codespeak.net (mwh at codespeak.net) Date: Thu, 14 Dec 2006 10:34:25 +0100 (CET) Subject: [pypy-svn] r35725 - pypy/dist/pypy/doc Message-ID: <20061214093425.8C30C1007A@code0.codespeak.net> Author: mwh Date: Thu Dec 14 10:34:21 2006 New Revision: 35725 Modified: pypy/dist/pypy/doc/index.txt Log: cli too! :) Modified: pypy/dist/pypy/doc/index.txt ============================================================================== --- pypy/dist/pypy/doc/index.txt (original) +++ pypy/dist/pypy/doc/index.txt Thu Dec 14 10:34:21 2006 @@ -124,7 +124,7 @@ PyPy's own tests, daily updated, `on Linux`_ and `on Windows`_ and on `build pypy-c`_ (various variants). -`Nightly builds and benchmarks`_ of PyPy to C and LLVM. +`Nightly builds and benchmarks`_ of PyPy to C, CLI and LLVM. `compliance test status`_ shows outcomes of recent compliance test runs against PyPy. From arigo at codespeak.net Thu Dec 14 10:36:37 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 14 Dec 2006 10:36:37 +0100 (CET) Subject: [pypy-svn] r35726 - pypy/dist/pypy/rpython Message-ID: <20061214093637.970D21007C@code0.codespeak.net> Author: arigo Date: Thu Dec 14 10:36:35 2006 New Revision: 35726 Modified: pypy/dist/pypy/rpython/controllerentry.py Log: Reordering methods. Modified: pypy/dist/pypy/rpython/controllerentry.py ============================================================================== --- pypy/dist/pypy/rpython/controllerentry.py (original) +++ pypy/dist/pypy/rpython/controllerentry.py Thu Dec 14 10:36:35 2006 @@ -48,17 +48,21 @@ revealargs=[], revealresult=True) - def ctrl_getattr(self, s_obj, s_attr): - return delegate(self.getattr, s_obj, s_attr) - def getattr(self, obj, attr): return getattr(self, 'get_' + attr)(obj) getattr._annspecialcase_ = 'specialize:arg(2)' + def ctrl_getattr(self, s_obj, s_attr): + return delegate(self.getattr, s_obj, s_attr) + def rtype_getattr(self, hop): r_controlled_instance = hop.args_r[0] return r_controlled_instance.rtypedelegate(self.getattr, hop) + def setattr(self, obj, attr, value): + return getattr(self, 'set_' + attr)(obj, value) + setattr._annspecialcase_ = 'specialize:arg(2)' + def ctrl_setattr(self, s_obj, s_attr, s_value): return delegate(self.setattr, s_obj, s_attr, s_value) @@ -66,10 +70,6 @@ r_controlled_instance = hop.args_r[0] return r_controlled_instance.rtypedelegate(self.setattr, hop) - def setattr(self, obj, attr, value): - return getattr(self, 'set_' + attr)(obj, value) - setattr._annspecialcase_ = 'specialize:arg(2)' - def delegate(boundmethod, *args_s): bk = getbookkeeper() From antocuni at codespeak.net Thu Dec 14 11:04:26 2006 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Thu, 14 Dec 2006 11:04:26 +0100 (CET) Subject: [pypy-svn] r35728 - pypy/dist/pypy/translator Message-ID: <20061214100426.A7CBA1008E@code0.codespeak.net> Author: antocuni Date: Thu Dec 14 11:04:25 2006 New Revision: 35728 Modified: pypy/dist/pypy/translator/driver.py Log: Place main.exe and pypylib.dll in a separate directory, so you can have multiple revision of the same target side-by-side. Modified: pypy/dist/pypy/translator/driver.py ============================================================================== --- pypy/dist/pypy/translator/driver.py (original) +++ pypy/dist/pypy/translator/driver.py Thu Dec 14 11:04:25 2006 @@ -594,15 +594,20 @@ usession_path, main_exe_name = os.path.split(main_exe) pypylib_dll = os.path.join(usession_path, 'pypylib.dll') - shutil.copy(main_exe, '.') - shutil.copy(pypylib_dll, '.') - newexename = self.exe_name % self.get_info() - if '/' not in newexename and '\\' not in newexename: - newexename = './' + newexename + basename = self.exe_name % self.get_info() + dirname = basename + '-data/' + if '/' not in dirname and '\\' not in dirname: + dirname = './' + dirname + + if not os.path.exists(dirname): + os.makedirs(dirname) + shutil.copy(main_exe, dirname) + shutil.copy(pypylib_dll, dirname) + newexename = basename f = file(newexename, 'w') f.write("""#!/bin/bash -mono "$(dirname $0)/%s" "$@" # XXX doesn't work if it's placed in PATH -""" % main_exe_name) +mono "$(dirname $0)/%s/%s" "$@" # XXX doesn't work if it's placed in PATH +""" % (dirname, main_exe_name)) f.close() os.chmod(newexename, 0755) From adim at codespeak.net Thu Dec 14 11:17:21 2006 From: adim at codespeak.net (adim at codespeak.net) Date: Thu, 14 Dec 2006 11:17:21 +0100 (CET) Subject: [pypy-svn] r35729 - pypy/branch/ast-experiments/pypy/interpreter/pyparser Message-ID: <20061214101721.1346310075@code0.codespeak.net> Author: adim Date: Thu Dec 14 11:17:18 2006 New Revision: 35729 Modified: pypy/branch/ast-experiments/pypy/interpreter/pyparser/ebnfgrammar.py Log: removing old / unused code Modified: pypy/branch/ast-experiments/pypy/interpreter/pyparser/ebnfgrammar.py ============================================================================== --- pypy/branch/ast-experiments/pypy/interpreter/pyparser/ebnfgrammar.py (original) +++ pypy/branch/ast-experiments/pypy/interpreter/pyparser/ebnfgrammar.py Thu Dec 14 11:17:18 2006 @@ -1,45 +1,9 @@ # This module contains the grammar parser # and the symbol mappings -from grammar import BaseGrammarBuilder, Alternative, Sequence, Token, \ - KleeneStar, GrammarElement, Parser +from grammar import Alternative, Sequence, Token, KleeneStar, \ + GrammarElement, Parser - -## sym_map = {} -## sym_rmap = {} -## _count = 0 - -## def g_add_symbol( name ): -## global _count -## if name in sym_rmap: -## return sym_rmap[name] -## val = _count -## _count += 1 -## sym_map[val] = name -## sym_rmap[name] = val -## globals()[name] = val -## return val - - -## tok_map = {} -## tok_rmap = {} - -## def g_add_token(sym, name): -## global _count -## if name in tok_rmap: -## return tok_rmap[name] -## val = _count -## _count += 1 -## tok_map[val] = name -## tok_rmap[name] = val -## sym_map[val] = sym -## sym_rmap[sym] = val -## globals()[sym] = val -## return val - - - -## g_add_token('EOF', 'EOF') class GrammarParser(Parser): pass @@ -62,7 +26,6 @@ option: '[' alternative ']' group: '(' alternative ')' star? """ - global sym_map p = GRAMMAR_GRAMMAR p.add_token('EOF','EOF') @@ -111,9 +74,4 @@ assert not hasattr( GRAMMAR_GRAMMAR, _sym ) setattr(GRAMMAR_GRAMMAR, _sym, _value ) -# cleanup -## del _sym -## del _value del grammar_grammar -## del g_add_symbol -# del g_add_token From pedronis at codespeak.net Thu Dec 14 13:59:06 2006 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Thu, 14 Dec 2006 13:59:06 +0100 (CET) Subject: [pypy-svn] r35734 - pypy/dist/pypy/rpython Message-ID: <20061214125906.2F9881008A@code0.codespeak.net> Author: pedronis Date: Thu Dec 14 13:59:04 2006 New Revision: 35734 Modified: pypy/dist/pypy/rpython/rstr.py Log: check (with assert) that nobody tries float(None) Modified: pypy/dist/pypy/rpython/rstr.py ============================================================================== --- pypy/dist/pypy/rpython/rstr.py (original) +++ pypy/dist/pypy/rpython/rstr.py Thu Dec 14 13:59:04 2006 @@ -610,6 +610,7 @@ from pypy.rpython.annlowlevel import hlstr from pypy.rlib.rarithmetic import break_up_float, parts_to_float s = hlstr(ll_str) + assert s is not None n = len(s) beg = 0 From antocuni at codespeak.net Thu Dec 14 13:59:24 2006 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Thu, 14 Dec 2006 13:59:24 +0100 (CET) Subject: [pypy-svn] r35735 - in pypy/dist/pypy: rpython/ootypesystem translator/cli translator/cli/src translator/cli/test Message-ID: <20061214125924.3DD8310091@code0.codespeak.net> Author: antocuni Date: Thu Dec 14 13:59:18 2006 New Revision: 35735 Modified: pypy/dist/pypy/rpython/ootypesystem/ooregistry.py pypy/dist/pypy/rpython/ootypesystem/ootype.py pypy/dist/pypy/rpython/ootypesystem/rstr.py pypy/dist/pypy/translator/cli/opcodes.py pypy/dist/pypy/translator/cli/src/pypylib.cs pypy/dist/pypy/translator/cli/test/test_float.py Log: Support for float(string) in ootypesystem and gencli. Modified: pypy/dist/pypy/rpython/ootypesystem/ooregistry.py ============================================================================== --- pypy/dist/pypy/rpython/ootypesystem/ooregistry.py (original) +++ pypy/dist/pypy/rpython/ootypesystem/ooregistry.py Thu Dec 14 13:59:18 2006 @@ -49,6 +49,24 @@ hop.exception_is_here() return hop.genop('ooparse_int', vlist, resulttype = ootype.Signed) + +class Entry_ooparse_float(ExtRegistryEntry): + _about_ = ootype.ooparse_float + + def compute_result_annotation(self, str_s): + assert isinstance(str_s, annmodel.SomeOOInstance)\ + and str_s.ootype is ootype.String + return annmodel.SomeFloat() + + def specialize_call(self, hop): + assert isinstance(hop.args_s[0], annmodel.SomeOOInstance)\ + and hop.args_s[0].ootype is ootype.String + vlist = hop.inputargs(hop.args_r[0]) + hop.has_implicit_exception(ValueError) + hop.exception_is_here() + return hop.genop('ooparse_float', vlist, resulttype = ootype.Float) + + class Entry_oohash(ExtRegistryEntry): _about_ = ootype.oohash Modified: pypy/dist/pypy/rpython/ootypesystem/ootype.py ============================================================================== --- pypy/dist/pypy/rpython/ootypesystem/ootype.py (original) +++ pypy/dist/pypy/rpython/ootypesystem/ootype.py Thu Dec 14 13:59:18 2006 @@ -1417,6 +1417,9 @@ def ooparse_int(s, base): return int(s._str, base) +def ooparse_float(s): + return float(s._str) + def setItemType(LIST, ITEMTYPE): return LIST._set_itemtype(ITEMTYPE) Modified: pypy/dist/pypy/rpython/ootypesystem/rstr.py ============================================================================== --- pypy/dist/pypy/rpython/ootypesystem/rstr.py (original) +++ pypy/dist/pypy/rpython/ootypesystem/rstr.py Thu Dec 14 13:59:18 2006 @@ -193,6 +193,9 @@ raise ValueError return sign * val + def ll_float(ll_str): + return ootype.ooparse_float(ll_str) + # interface to build strings: # x = ll_build_start(n) # ll_build_push(x, next_string, 0) Modified: pypy/dist/pypy/translator/cli/opcodes.py ============================================================================== --- pypy/dist/pypy/translator/cli/opcodes.py (original) +++ pypy/dist/pypy/translator/cli/opcodes.py Thu Dec 14 13:59:18 2006 @@ -49,6 +49,7 @@ 'oohash': [PushAllArgs, 'callvirt instance int32 object::GetHashCode()'], 'oostring': [OOString], 'ooparse_int': [PushAllArgs, 'call int32 [pypylib]pypy.runtime.Utils::OOParseInt(string, int32)'], + 'ooparse_float': [PushAllArgs, 'call float64 [pypylib]pypy.runtime.Utils::OOParseFloat(string)'], 'oonewcustomdict': [NewCustomDict], 'same_as': DoNothing, 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 Dec 14 13:59:18 2006 @@ -108,6 +108,17 @@ return Convert.ToInt32(s, base_); } + public static double OOParseFloat(string s) + { + try { + return Double.Parse(s.Trim()); + } + catch(FormatException e) { + Helpers.raise_ValueError(); + return -1; + } + } + public static bool Equal(T t1, T t2) { return t1.Equals(t2); Modified: pypy/dist/pypy/translator/cli/test/test_float.py ============================================================================== --- pypy/dist/pypy/translator/cli/test/test_float.py (original) +++ pypy/dist/pypy/translator/cli/test/test_float.py Thu Dec 14 13:59:18 2006 @@ -5,3 +5,16 @@ class TestCliFloat(CliTest, BaseTestRfloat): pass + def test_float(self): + ex = ['', ' ', '0', '1', '-1.5', '1.5E2', '2.5e-1', ' 0 ', '?'] + def fn(i): + s = ex[i] + try: + return float(s) + except ValueError: + return -999.0 + + for i in range(len(ex)): + expected = fn(i) + res = self.interpret(fn, [i]) + assert res == expected From ericvrp at codespeak.net Thu Dec 14 14:44:34 2006 From: ericvrp at codespeak.net (ericvrp at codespeak.net) Date: Thu, 14 Dec 2006 14:44:34 +0100 (CET) Subject: [pypy-svn] r35738 - in pypy/dist/pypy/jit/codegen/llvm: . test Message-ID: <20061214134434.A679C1007F@code0.codespeak.net> Author: ericvrp Date: Thu Dec 14 14:44:33 2006 New Revision: 35738 Modified: pypy/dist/pypy/jit/codegen/llvm/rgenop.py pypy/dist/pypy/jit/codegen/llvm/test/test_operation.py Log: The llvm instruction set is currently in flux in anticipation of llvm 2.0. This checkin contains fixes for the removal of the rem and cast instruction in jit/codegen/llvm. Something similar probably needs to be done in translator/llvm, at least when using llvm cvs head. Modified: pypy/dist/pypy/jit/codegen/llvm/rgenop.py ============================================================================== --- pypy/dist/pypy/jit/codegen/llvm/rgenop.py (original) +++ pypy/dist/pypy/jit/codegen/llvm/rgenop.py Thu Dec 14 14:44:33 2006 @@ -328,14 +328,14 @@ def op_int_sub(self, gv_x, gv_y): return self._rgenop2_generic('sub' , gv_x, gv_y) def op_int_mul(self, gv_x, gv_y): return self._rgenop2_generic('mul' , gv_x, gv_y) def op_int_floordiv(self, gv_x, gv_y): return self._rgenop2_generic('sdiv', gv_x, gv_y) - def op_int_mod(self, gv_x, gv_y): return self._rgenop2_generic('rem' , gv_x, gv_y) + def op_int_mod(self, gv_x, gv_y): return self._rgenop2_generic('srem' , gv_x, gv_y) def op_int_and(self, gv_x, gv_y): return self._rgenop2_generic('and' , gv_x, gv_y) def op_int_or(self, gv_x, gv_y): return self._rgenop2_generic('or' , gv_x, gv_y) def op_int_xor(self, gv_x, gv_y): return self._rgenop2_generic('xor' , gv_x, gv_y) def op_int_lshift(self, gv_x, gv_y): gv_y_ubyte = Var('ubyte') - self.asm.append(' %s=cast %s to ubyte' % (gv_y_ubyte.operand2(), gv_y.operand())) + self.asm.append(' %s=trunc %s to ubyte' % (gv_y_ubyte.operand2(), gv_y.operand())) gv_result = Var(gv_x.type) self.asm.append(' %s=shl %s,%s' % ( gv_result.operand2(), gv_x.operand(), gv_y_ubyte.operand())) @@ -343,9 +343,10 @@ def op_int_rshift(self, gv_x, gv_y): gv_y_ubyte = Var('ubyte') - self.asm.append(' %s=cast %s to ubyte' % (gv_y_ubyte.operand2(), gv_y.operand())) + self.asm.append(' %s=trunc %s to ubyte' % (gv_y_ubyte.operand2(), gv_y.operand())) gv_result = Var(gv_x.type) - self.asm.append(' %s=shr %s,%s' % ( + #XXX lshr/ashr + self.asm.append(' %s=lshr %s,%s' % ( gv_result.operand2(), gv_x.operand(), gv_y_ubyte.operand())) return gv_result @@ -407,10 +408,29 @@ #def op_bool_not(self, gv_x): #use select, xor or sub XXXX todo: did not see a test for this + #XXX 'cast' has been replaced by many sext/zext/uitofp/... opcodes in the upcoming llvm 2.0. + #The lines upto /XXX should be refactored to do the right thing + def op_same_as(self, gv_x): + gv_result = Var(gv_x.type) + self.asm.append(' %s=bitcast %s to %s' % ( + gv_result.operand2(), gv_x.operand(), gv_x.type)) + return gv_result + def _cast_to(self, gv_x, restype=None): restype = restype or gv_x.type + if restype is gv_x.type: + return self.op_same_as(gv_x) + gv_result = Var(restype) + self.asm.append(' %s=zext %s to %s' % ( + gv_result.operand2(), gv_x.operand(), restype)) + return gv_result + + def _trunc_to(self, gv_x, restype=None): + restype = restype or gv_x.type + if restype is gv_x.type: + return self.op_same_as(gv_x) gv_result = Var(restype) - self.asm.append(' %s=cast %s to %s' % ( + self.asm.append(' %s=trunc %s to %s' % ( gv_result.operand2(), gv_x.operand(), restype)) return gv_result @@ -421,41 +441,49 @@ def _cast_to_uint(self, gv_x): return self._cast_to(gv_x, 'uint') def _cast_to_float(self, gv_x): return self._cast_to(gv_x, 'float') - op_cast_char_to_bool = _cast_to_bool - op_cast_unichar_to_bool = _cast_to_bool - op_cast_int_to_bool = _cast_to_bool - op_cast_uint_to_bool = _cast_to_bool - op_cast_float_to_bool = _cast_to_bool + def _trunc_to_bool(self, gv_x): return self._trunc_to(gv_x, 'bool') + def _trunc_to_char(self, gv_x): return self._trunc_to(gv_x, 'ubyte') + def _trunc_to_unichar(self, gv_x): return self._trunc_to(gv_x, 'int') + def _trunc_to_int(self, gv_x): return self._trunc_to(gv_x, 'int') + def _trunc_to_uint(self, gv_x): return self._trunc_to(gv_x, 'uint') + def _trunc_to_float(self, gv_x): return self._trunc_to(gv_x, 'float') + + op_cast_char_to_bool = _trunc_to_bool + op_cast_unichar_to_bool = _trunc_to_bool + op_cast_int_to_bool = _trunc_to_bool + op_cast_uint_to_bool = _trunc_to_bool + op_cast_float_to_bool = _trunc_to_bool op_cast_bool_to_char = _cast_to_char - op_cast_unichar_to_char = _cast_to_char - op_cast_int_to_char = _cast_to_char - op_cast_uint_to_char = _cast_to_char - op_cast_float_to_char = _cast_to_char + op_cast_unichar_to_char = _trunc_to_char + op_cast_int_to_char = _trunc_to_char + op_cast_uint_to_char = _trunc_to_char + op_cast_float_to_char = _trunc_to_char op_cast_bool_to_unichar = _cast_to_unichar op_cast_char_to_unichar = _cast_to_unichar op_cast_int_to_unichar = _cast_to_unichar op_cast_uint_to_unichar = _cast_to_unichar - op_cast_float_to_unichar = _cast_to_unichar + op_cast_float_to_unichar = _trunc_to_unichar op_cast_bool_to_int = _cast_to_int op_cast_char_to_int = _cast_to_int op_cast_unichar_to_int = _cast_to_int op_cast_uint_to_int = _cast_to_int - op_cast_float_to_int = _cast_to_int + op_cast_float_to_int = _trunc_to_int op_cast_bool_to_uint = _cast_to_uint op_cast_char_to_uint = _cast_to_uint op_cast_unichar_to_uint = _cast_to_uint op_cast_int_to_uint = _cast_to_uint - op_cast_float_to_uint = _cast_to_uint + op_cast_float_to_uint = _trunc_to_uint op_cast_bool_to_float = _cast_to_float op_cast_char_to_float = _cast_to_float op_cast_unichar_to_float = _cast_to_float op_cast_int_to_float = _cast_to_float op_cast_uint_to_float = _cast_to_float + #/XXX def enter_next_block(self, kinds, args_gv): # if nextlabel is None, it means that we are currently Modified: pypy/dist/pypy/jit/codegen/llvm/test/test_operation.py ============================================================================== --- pypy/dist/pypy/jit/codegen/llvm/test/test_operation.py (original) +++ pypy/dist/pypy/jit/codegen/llvm/test/test_operation.py Thu Dec 14 14:44:33 2006 @@ -4,7 +4,7 @@ from pypy.jit.codegen.llvm.rgenop import RLLVMGenOp -skip_unsupported_platform() +#skip_unsupported_platform() class LLVMTestBasicMixin(object): From ericvrp at codespeak.net Thu Dec 14 14:51:17 2006 From: ericvrp at codespeak.net (ericvrp at codespeak.net) Date: Thu, 14 Dec 2006 14:51:17 +0100 (CET) Subject: [pypy-svn] r35739 - pypy/dist/pypy/jit/codegen/llvm Message-ID: <20061214135117.C3D121007B@code0.codespeak.net> Author: ericvrp Date: Thu Dec 14 14:51:16 2006 New Revision: 35739 Modified: pypy/dist/pypy/jit/codegen/llvm/rgenop.py Log: And another int to ptr cast solved. (this particular test was not run on my OSX machine because the gc library was not found) Modified: pypy/dist/pypy/jit/codegen/llvm/rgenop.py ============================================================================== --- pypy/dist/pypy/jit/codegen/llvm/rgenop.py (original) +++ pypy/dist/pypy/jit/codegen/llvm/rgenop.py Thu Dec 14 14:51:16 2006 @@ -148,7 +148,7 @@ # check the types for debugging sourcevartypes = [var.type for var in sourcevars] targetvartypes = [var.type for var in self.inputargs] - #XXX ERIC assert sourcevartypes == targetvartypes + assert sourcevartypes == targetvartypes # Check if the source block jumps to 'self' from multiple # positions: in this case we need an intermediate block... @@ -602,7 +602,7 @@ gv_result = Var('ubyte*') gv_gc_malloc_fnaddr = Var('[0xubyte]* (int)*') #XXX or use addGlobalFunctionMapping in libllvmjit.restart() - self.asm.append(' %s=cast int %d to %s ;gc_malloc_fnaddr' % ( + self.asm.append(' %s=inttoptr int %d to %s ;gc_malloc_fnaddr' % ( gv_gc_malloc_fnaddr.operand2(), gc_malloc_fnaddr(), gv_gc_malloc_fnaddr.type)) self.asm.append(' %s=call %s(int %d)' % ( gv_result.operand2(), gv_gc_malloc_fnaddr.operand(), size)) @@ -626,7 +626,7 @@ gv_result = Var('ubyte*') gv_gc_malloc_fnaddr = Var('[0xubyte]* (int)*') #XXX or use addGlobalFunctionMapping in libllvmjit.restart() - self.asm.append(' %s=cast int %d to %s ;gc_malloc_fnaddr' % ( + self.asm.append(' %s=inttoptr int %d to %s ;gc_malloc_fnaddr' % ( gv_gc_malloc_fnaddr.operand2(), gc_malloc_fnaddr(), gv_gc_malloc_fnaddr.type)) self.asm.append(' %s=call %s(%s)' % ( gv_result.operand2(), gv_gc_malloc_fnaddr.operand(), gv_size.operand())) From antocuni at codespeak.net Thu Dec 14 15:10:29 2006 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Thu, 14 Dec 2006 15:10:29 +0100 (CET) Subject: [pypy-svn] r35741 - in pypy/dist/pypy/translator: cli cli/test oosupport Message-ID: <20061214141029.230FD1007A@code0.codespeak.net> Author: antocuni Date: Thu Dec 14 15:10:27 2006 New Revision: 35741 Modified: pypy/dist/pypy/translator/cli/function.py pypy/dist/pypy/translator/cli/ilgenerator.py pypy/dist/pypy/translator/cli/metavm.py pypy/dist/pypy/translator/cli/test/runtest.py pypy/dist/pypy/translator/cli/test/test_exception.py pypy/dist/pypy/translator/oosupport/function.py Log: Hack to make gencli not use native .NET exceptions for the RPython ones. It is disabled by default. We need a saner way to do this, it will be removed in the future. Modified: pypy/dist/pypy/translator/cli/function.py ============================================================================== --- pypy/dist/pypy/translator/cli/function.py (original) +++ pypy/dist/pypy/translator/cli/function.py Thu Dec 14 15:10:27 2006 @@ -15,23 +15,9 @@ from pypy.translator.cli.support import log from pypy.translator.cli.ilgenerator import CLIBaseGenerator -class Function(OOFunction, Node, CLIBaseGenerator): - - def __init__(self, *args, **kwargs): - OOFunction.__init__(self, *args, **kwargs) - self._set_args() - self._set_locals() - - def _create_generator(self, ilasm): - return self # Function implements the Generator interface - - def record_ll_meta_exc(self, ll_meta_exc): - # record the type only if it doesn't belong to a native_class - ll_exc = ll_meta_exc._inst.class_._INSTANCE - NATIVE_INSTANCE = ll_exc._hints.get('NATIVE_INSTANCE', None) - if NATIVE_INSTANCE is None: - OOFunction.record_ll_meta_exc(self, ll_meta_exc) +USE_LAST = False +class NativeExceptionHandler(object): def begin_try(self): self.ilasm.begin_try() @@ -49,6 +35,67 @@ self.ilasm.leave(target_label) self.ilasm.end_catch() + def render_raise_block(self, block): + exc = block.inputargs[1] + self.load(exc) + self.ilasm.opcode('throw') + + def store_exception_and_link(self, link): + if self._is_raise_block(link.target): + # the exception value is on the stack, use it as the 2nd target arg + assert len(link.args) == 2 + assert len(link.target.inputargs) == 2 + self.store(link.target.inputargs[1]) + else: + # the exception value is on the stack, store it in the proper place + if isinstance(link.last_exception, flowmodel.Variable): + self.ilasm.opcode('dup') + self.store(link.last_exc_value) + self.ilasm.get_field(('class Object_meta', 'Object', 'meta')) + self.store(link.last_exception) + else: + self.store(link.last_exc_value) + self._setup_link(link) + +class LastExceptionHandler(object): + catch_label_count = 0 + in_try = False + + def next_catch_label(self): + self.catch_label_count += 1 + return self.catch_label() + + def catch_label(self): + return '__catch_%d' % self.catch_label_count + + def begin_try(self): + self.in_try = True + self.ilasm.opcode('// begin_try') + + def end_try(self, target_label): + self.ilasm.opcode('ldsfld', 'object last_exception') + self.ilasm.opcode('brnull', target_label) + self.ilasm.opcode('// end try') + self.in_try = False + + def begin_catch(self, llexitcase): + self.ilasm.label(self.catch_label()) + ll_meta_exc = llexitcase + ll_exc = ll_meta_exc._inst.class_._INSTANCE + cts_exc = self.cts.lltype_to_cts(ll_exc, False) + self.ilasm.opcode('ldsfld', 'object last_exception') + self.isinstance(cts_exc) + self.ilasm.opcode('dup') + self.ilasm.opcode('brtrue.s', 6) # ?? + self.ilasm.opcode('pop') + self.ilasm.opcode('br', self.next_catch_label()) + # here is the target of the above brtrue.s + self.ilasm.opcode('ldnull') + self.ilasm.opcode('stsfld', 'object last_exception') + + def end_catch(self, target_label): + self.ilasm.opcode('br', target_label) + def store_exception_and_link(self, link): if self._is_raise_block(link.target): # the exception value is on the stack, use it as the 2nd target arg @@ -66,6 +113,84 @@ self.store(link.last_exc_value) self._setup_link(link) + def render_raise_block(self, block): + exc = block.inputargs[1] + self.load(exc) + self.ilasm.opcode('stsfld', 'object last_exception') + if not self.return_block: # must be a void function + TYPE = self.graph.getreturnvar().concretetype + default = TYPE._defl() + if default is not None: # concretetype is Void + try: + self.db.constant_generator.push_primitive_constant(self, TYPE, default) + except AssertionError: + self.ilasm.opcode('ldnull') # :-( + self.ilasm.opcode('ret') + else: + self.ilasm.opcode('br', self._get_block_name(self.return_block)) + + + def _render_op(self, op): + from pypy.rpython.ootypesystem import ootype + instr_list = self.db.genoo.opcodes.get(op.opname, None) + assert instr_list is not None, 'Unknown opcode: %s ' % op + assert isinstance(instr_list, InstructionList) + instr_list.render(self.generator, op) + if op.opname in ('direct_call', 'oosend', 'indirect_call') and not self.in_try: + self._premature_return() + + def _premature_return(self): + try: + return_block = self._get_block_name(self.graph.returnblock) + except KeyError: + self.ilasm.opcode('//premature return') + self.ilasm.opcode('ldsfld', 'object last_exception') + TYPE = self.graph.getreturnvar().concretetype + default = TYPE._defl() + if default is None: # concretetype is Void + self.ilasm.opcode('brfalse.s', 1) + self.ilasm.opcode('ret') + else: + self.ilasm.opcode('brfalse.s', 3) # ?? + try: + self.db.constant_generator.push_primitive_constant(self, TYPE, default) + except AssertionError: + self.ilasm.opcode('ldnull') # :-( + self.ilasm.opcode('ret') + else: + self.ilasm.opcode('ldsfld', 'object last_exception') + self.ilasm.opcode('brtrue', return_block) + + +if USE_LAST: + ExceptionHandler = LastExceptionHandler +else: + ExceptionHandler = NativeExceptionHandler + +class Function(ExceptionHandler, OOFunction, Node, CLIBaseGenerator): + + def next_catch_label(self): + self.catch_label_count += 1 + return self.catch_label() + + def catch_label(self): + return '__catch_%d' % self.catch_label_count + + def __init__(self, *args, **kwargs): + OOFunction.__init__(self, *args, **kwargs) + self._set_args() + self._set_locals() + + def _create_generator(self, ilasm): + return self # Function implements the Generator interface + + def record_ll_meta_exc(self, ll_meta_exc): + # record the type only if it doesn't belong to a native_class + ll_exc = ll_meta_exc._inst.class_._INSTANCE + NATIVE_INSTANCE = ll_exc._hints.get('NATIVE_INSTANCE', None) + if NATIVE_INSTANCE is None: + OOFunction.record_ll_meta_exc(self, ll_meta_exc) + def begin_render(self): returntype, returnvar = self.cts.llvar_to_cts(self.graph.getreturnvar()) if self.is_method: @@ -77,6 +202,13 @@ self.ilasm.begin_function(self.name, args, returntype, self.is_entrypoint, meth_type) self.ilasm.locals(self.locals) + def before_last_blocks(self): + # This is only executed when using LastExceptionHandler. + # Need to be deleted when we will use a saner approach. + if hasattr(self, 'catch_label'): + self.ilasm.label(self.catch_label()) + self.ilasm.opcode('nop') + def end_render(self): self.ilasm.end_function() @@ -89,12 +221,6 @@ self.load(return_var) self.ilasm.opcode('ret') - def render_raise_block(self, block): - exc = block.inputargs[1] - self.load(exc) - self.ilasm.opcode('throw') - - # Those parts of the generator interface that are function # specific Modified: pypy/dist/pypy/translator/cli/ilgenerator.py ============================================================================== --- pypy/dist/pypy/translator/cli/ilgenerator.py (original) +++ pypy/dist/pypy/translator/cli/ilgenerator.py Thu Dec 14 15:10:27 2006 @@ -55,6 +55,7 @@ self.code.writeline('.assembly extern mscorlib {}') self.code.writeline('.assembly extern pypylib {}') self.code.writeline('.assembly %s {}' % name) + self.code.writeline('.field static object last_exception') # XXX def close(self): self.out.close() Modified: pypy/dist/pypy/translator/cli/metavm.py ============================================================================== --- pypy/dist/pypy/translator/cli/metavm.py (original) +++ pypy/dist/pypy/translator/cli/metavm.py Thu Dec 14 15:10:27 2006 @@ -154,6 +154,12 @@ self.mapping = mapping def render(self, generator, op): + if hasattr(self, 'catch_label'): + self.render_last(generator, op) + else: + self.render_native(generator, op) + + def render_native(self, generator, op): ilasm = generator.ilasm label = '__check_block_%d' % MapException.COUNT MapException.COUNT += 1 @@ -169,6 +175,25 @@ ilasm.label(label) ilasm.opcode('nop') + def render_last(self, generator, op): + ilasm = generator.ilasm + stdflow = '__check_block_%d' % MapException.COUNT + MapException.COUNT += 1 + premature_return = '__check_block_%d' % MapException.COUNT + MapException.COUNT += 1 + ilasm.begin_try() + self.instr.render(generator, op) + ilasm.leave(stdflow) + ilasm.end_try() + for cli_exc, py_exc in self.mapping: + ilasm.begin_catch(cli_exc) + ilasm.new('instance void class %s::.ctor()' % py_exc) + ilasm.opcode('stsfld', 'object last_exception') + ilasm.leave(stdflow) + ilasm.end_catch() + ilasm.label(stdflow) + ilasm.opcode('nop') + class _Box(MicroInstruction): def render(self, generator, op): generator.load(op.args[0]) Modified: pypy/dist/pypy/translator/cli/test/runtest.py ============================================================================== --- pypy/dist/pypy/translator/cli/test/runtest.py (original) +++ pypy/dist/pypy/translator/cli/test/runtest.py Thu Dec 14 15:10:27 2006 @@ -58,6 +58,11 @@ def render(self, ilasm): ilasm.begin_function('main', [('string[]', 'argv')], 'void', True, 'static') + RETURN_TYPE = self.graph.getreturnvar().concretetype + return_type = self.cts.lltype_to_cts(RETURN_TYPE) + if return_type != 'void': + ilasm.locals([(return_type, 'res')]) + if self.wrap_exceptions: ilasm.begin_try() @@ -72,10 +77,12 @@ # call the function and convert the result to a string containing a valid python expression ilasm.call(self.cts.graph_to_signature(self.graph)) - TYPE = self.graph.getreturnvar().concretetype - format_object(TYPE, self.cts, ilasm) - ilasm.call('void class [mscorlib]System.Console::WriteLine(string)') - ilasm.leave('return') + if return_type != 'void': + ilasm.opcode('stloc', 'res') + if self.wrap_exceptions: + ilasm.leave('check_last_exception') + else: + ilasm.leave('print_result') if self.wrap_exceptions: ilasm.end_try() @@ -90,6 +97,21 @@ ilasm.leave('return') ilasm.end_catch() + ilasm.label('check_last_exception') + ilasm.opcode('ldsfld', 'object last_exception') + ilasm.opcode('brnull', 'print_result') + # there is a pending exception + ilasm.opcode('ldsfld', 'object last_exception') + ilasm.call('string class [pypylib]pypy.test.Result::FormatException(object)') + ilasm.call('void class [mscorlib]System.Console::WriteLine(string)') + ilasm.opcode('br', 'return') + + ilasm.label('print_result') + if return_type != 'void': + ilasm.opcode('ldloc', 'res') + format_object(RETURN_TYPE, self.cts, ilasm) + ilasm.call('void class [mscorlib]System.Console::WriteLine(string)') + ilasm.label('return') ilasm.opcode('ret') ilasm.end_function() @@ -140,6 +162,8 @@ t.view() t.buildrtyper(type_system="ootype").specialize() + + main_graph = t.graphs[0] if getoption('view'): Modified: pypy/dist/pypy/translator/cli/test/test_exception.py ============================================================================== --- pypy/dist/pypy/translator/cli/test/test_exception.py (original) +++ pypy/dist/pypy/translator/cli/test/test_exception.py Thu Dec 14 15:10:27 2006 @@ -38,3 +38,20 @@ def test_raise_prebuilt_and_catch_other(self): pass + + def test_missing_return_block(self): + class Base: + def foo(self): + raise ValueError + + class Derived(Base): + def foo(self): + return 42 + + def fn(x): + if x: + obj = Base() + else: + obj = Derived() + return obj.foo() + assert self.interpret(fn, [0]) == 42 Modified: pypy/dist/pypy/translator/oosupport/function.py ============================================================================== --- pypy/dist/pypy/translator/oosupport/function.py (original) +++ pypy/dist/pypy/translator/oosupport/function.py Thu Dec 14 15:10:27 2006 @@ -82,15 +82,16 @@ graph = self.graph self.begin_render() - return_blocks = [] + self.return_block = None + self.raise_block = None for block in graph.iterblocks(): if self._is_return_block(block): - return_blocks.append(block) + self.return_block = block + elif self._is_raise_block(block): + self.raise_block = block else: self.set_label(self._get_block_name(block)) - if self._is_raise_block(block): - self.render_raise_block(block) - elif self._is_exc_handling_block(block): + if self._is_exc_handling_block(block): self.render_exc_handling_block(block) else: self.render_normal_block(block) @@ -98,14 +99,23 @@ # render return blocks at the end just to please the .NET # runtime that seems to need a return statement at the end of # the function - for block in return_blocks: - self.set_label(self._get_block_name(block)) - self.render_return_block(block) + + self.before_last_blocks() + + if self.raise_block: + self.set_label(self._get_block_name(self.raise_block)) + self.render_raise_block(self.raise_block) + if self.return_block: + self.set_label(self._get_block_name(self.return_block)) + self.render_return_block(self.return_block) self.end_render() if not self.is_method: self.db.record_function(self.graph, self.name) + def before_last_blocks(self): + pass + def render_exc_handling_block(self, block): # renders all ops but the last one for op in block.operations[:-1]: From arigo at codespeak.net Thu Dec 14 16:04:57 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 14 Dec 2006 16:04:57 +0100 (CET) Subject: [pypy-svn] r35743 - in pypy/dist/pypy: rlib rlib/rctypes rlib/rctypes/test rlib/test rpython rpython/rctypes rpython/test Message-ID: <20061214150457.6F3411007C@code0.codespeak.net> Author: arigo Date: Thu Dec 14 16:04:53 2006 New Revision: 35743 Added: pypy/dist/pypy/rlib/rctypes/ (props changed) pypy/dist/pypy/rlib/rctypes/__init__.py (contents, props changed) pypy/dist/pypy/rlib/rctypes/implementation.py (contents, props changed) pypy/dist/pypy/rlib/rctypes/rarray.py (contents, props changed) pypy/dist/pypy/rlib/rctypes/rctypesobject.py - copied unchanged from r35732, pypy/dist/pypy/rlib/rctypesobject.py pypy/dist/pypy/rlib/rctypes/rpointer.py (contents, props changed) pypy/dist/pypy/rlib/rctypes/rprimitive.py - copied, changed from r35732, pypy/dist/pypy/rpython/rctypes/aprimitive.py pypy/dist/pypy/rlib/rctypes/test/ (props changed) pypy/dist/pypy/rlib/rctypes/test/test_rctypesobject.py - copied, changed from r35732, pypy/dist/pypy/rlib/test/test_rctypesobject.py pypy/dist/pypy/rlib/rctypes/test/test_rprimitive.py - copied, changed from r35732, pypy/dist/pypy/rpython/rctypes/test/test_rprimitive.py Removed: pypy/dist/pypy/rlib/rctypesobject.py pypy/dist/pypy/rlib/test/test_rctypesobject.py Modified: pypy/dist/pypy/rpython/controllerentry.py pypy/dist/pypy/rpython/rcontrollerentry.py pypy/dist/pypy/rpython/rctypes/implementation.py pypy/dist/pypy/rpython/test/test_controllerentry.py Log: Start implementing rctypes on top of rctypesobject using the controllerentry mechanism. It seems to work. It's completely obscure, though. Added: pypy/dist/pypy/rlib/rctypes/__init__.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/rlib/rctypes/__init__.py Thu Dec 14 16:04:53 2006 @@ -0,0 +1 @@ +# empty Added: pypy/dist/pypy/rlib/rctypes/implementation.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/rlib/rctypes/implementation.py Thu Dec 14 16:04:53 2006 @@ -0,0 +1,151 @@ +from pypy.annotation import model as annmodel +from pypy.rlib.rctypes import rctypesobject +from pypy.rpython import extregistry, controllerentry +from pypy.rpython.controllerentry import Controller, ControllerEntry +from pypy.rpython.controllerentry import ControllerEntryForPrebuilt +from pypy.rpython.controllerentry import SomeControlledInstance +from pypy.rpython.lltypesystem import lltype +from pypy.rpython.rctypes import rcarithmetic as rcarith + +import ctypes +if ctypes.__version__ < '0.9.9.6': # string comparison... good enough? + raise ImportError("requires ctypes >= 0.9.9.6, got %s" % ( + ctypes.__version__,)) + + +class CTypeController(Controller): + + def __init__(self, ctype): + self.ctype = ctype + self.instance_cache = {} + + def register_for_type(cls, ctype): + class Entry(CTypesCallEntry): + _about_ = ctype + _controller_ = cls + class Entry(CTypesObjEntry): + _type_ = ctype + _controller_ = cls + register_for_type = classmethod(register_for_type) + + def register_for_metatype(cls, ctype): + class Entry(CTypesCallEntry): + _type_ = ctype + _controller_ = cls + class Entry(CTypesObjEntry): + _metatype_ = ctype + _controller_ = cls + register_for_metatype = classmethod(register_for_metatype) + + def convert(self, x): + assert isinstance(x, self.ctype) + key = id(x) + try: + return self.instance_cache[key] + except KeyError: + obj = self.new() + self.instance_cache[key] = obj + self.initialize_prebuilt(obj, x) + return obj + + def return_value(self, obj): + return obj + return_value._annspecialcase_ = 'specialize:arg(0)' + + # extension to the setattr/setitem support: if the new value is actually + # a CTypeControlled instance as well, reveal it automatically (i.e. turn + # it into an rctypesobject) and call a method with a different name. + + def setboxattr(self, obj, attr, value): + return getattr(self, 'setbox_' + attr)(obj, value) + setboxattr._annspecialcase_ = 'specialize:arg(2)' + + def ctrl_setattr(self, s_obj, s_attr, s_value): + if s_is_box(s_value): + return controllerentry.delegate(self.setboxattr, + s_obj, s_attr, s_value.s_real_obj) + else: + return controllerentry.delegate(self.setattr, + s_obj, s_attr, s_value) + + def rtype_setattr(self, hop): + r_controlled_instance = hop.args_r[0] + if s_is_box(hop.args_s[2]): + hop2 = revealbox(hop, 2) + return r_controlled_instance.rtypedelegate(self.setboxattr, hop2) + else: + return r_controlled_instance.rtypedelegate(self.setattr, hop) + + def ctrl_setitem(self, s_obj, s_key, s_value): + if s_is_box(s_value): + return controllerentry.delegate(self.setboxitem, + s_obj, s_key, s_value.s_real_obj) + else: + return controllerentry.delegate(self.setitem, + s_obj, s_key, s_value) + + def rtype_setitem(self, hop): + r_controlled_instance = hop.args_r[0] + if s_is_box(hop.args_s[2]): + hop2 = revealbox(hop, 2) + return r_controlled_instance.rtypedelegate(self.setboxitem, hop2) + else: + return r_controlled_instance.rtypedelegate(self.setitem, hop) + + +class CTypesCallEntry(ControllerEntry): + def getcontroller(self, *args_s): + ctype = self.instance + return self._controller_(ctype) + +class CTypesObjEntry(ControllerEntryForPrebuilt): + def getcontroller(self): + ctype = self.type + return self._controller_(ctype) + +def getcontroller(ctype): + """Return the CTypeController instance corresponding to the given ctype.""" + entry = extregistry.lookup_type(ctype) + return entry.getcontroller() + +def s_is_box(s_value): + return (isinstance(s_value, SomeControlledInstance) and + isinstance(s_value.controller, CTypeController)) + +def revealbox(hop, argindex): + hop2 = hop.copy() + r_value = hop2.args_r[argindex] + s_value, r_value = r_value.reveal(r_value) + hop2.args_s[argindex] = s_value + hop2.args_r[argindex] = r_value + return hop2 + +def register_function_impl(builtinfn, controllingfn, + revealargs=[], revealresult=None): + + class Entry(extregistry.ExtRegistryEntry): + _about_ = builtinfn + + def compute_result_annotation(self, *args_s): + real_args_s = list(args_s) + for index in revealargs: + real_args_s[index] = args_s[index].s_real_obj + if annmodel.s_ImpossibleValue in real_args_s: + return annmodel.s_ImpossibleValue # temporarily hopefully + s_result = controllerentry.delegate(controllingfn, *real_args_s) + if revealresult: + result_ctype = revealresult(*args_s) + controller = getcontroller(result_ctype) + s_result = SomeControlledInstance(s_result, controller) + return s_result + + def specialize_call(self, hop): + import pdb; pdb.set_trace() + +# ____________________________________________________________ +# +# Imports for side-effects + +import pypy.rlib.rctypes.rprimitive +import pypy.rlib.rctypes.rarray +import pypy.rlib.rctypes.rpointer Added: pypy/dist/pypy/rlib/rctypes/rarray.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/rlib/rctypes/rarray.py Thu Dec 14 16:04:53 2006 @@ -0,0 +1,44 @@ +from pypy.rlib.rctypes.implementation import CTypeController, getcontroller +from pypy.rlib.rctypes import rctypesobject +from pypy.rpython.lltypesystem import lltype + +from ctypes import ARRAY, c_int, c_char + + +ArrayType = type(ARRAY(c_int, 10)) + + +class ArrayCTypeController(CTypeController): + + def __init__(self, ctype): + CTypeController.__init__(self, ctype) + self.itemcontroller = getcontroller(ctype._type_) + self.length = ctype._length_ + self.knowntype = rctypesobject.RFixedArray( + self.itemcontroller.knowntype, + self.length) + + def new(self, *args_s): + if len(args_s) > self.length: + raise ValueError("too many arguments for an array of length %d" % ( + self.length,)) + obj = self.knowntype.allocate() + if len(args_s) > 0: + lst_s = list(args_s) + for i in range(len(args_s)): + self.setitem(obj, i, lst_s[i]) + return obj + new._annspecialcase_ = 'specialize:arg(0)' + + def getitem(self, obj, i): + itemobj = obj.ref(i) + return self.itemcontroller.return_value(itemobj) + getitem._annspecialcase_ = 'specialize:arg(0)' + + def setitem(self, obj, i, value): + itemobj = obj.ref(i) + self.itemcontroller.set_value(itemobj, value) + setitem._annspecialcase_ = 'specialize:arg(0)' + + +ArrayCTypeController.register_for_metatype(ArrayType) Added: pypy/dist/pypy/rlib/rctypes/rpointer.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/rlib/rctypes/rpointer.py Thu Dec 14 16:04:53 2006 @@ -0,0 +1,38 @@ +from pypy.rpython.extregistry import ExtRegistryEntry +from pypy.rlib.rctypes.implementation import CTypeController, getcontroller +from pypy.rlib.rctypes.implementation import register_function_impl +from pypy.rlib.rctypes import rctypesobject +from pypy.rpython.lltypesystem import lltype + +from ctypes import pointer, POINTER, byref, c_int + + +PointerType = type(POINTER(c_int)) + + +class PointerCTypeController(CTypeController): + + def __init__(self, ctype): + CTypeController.__init__(self, ctype) + self.contentscontroller = getcontroller(ctype._type_) + self.knowntype = rctypesobject.RPointer( + self.contentscontroller.knowntype) + + def new(self): + obj = self.knowntype.allocate() + #... + return obj + + def getitem(self, obj, index): + if index != 0: + raise ValueError("can only access item 0 of pointers") + contentsobj = obj.get_contents() + return self.contentscontroller.return_value(contentsobj) + getitem._annspecialcase_ = 'specialize:arg(0)' + +PointerCTypeController.register_for_metatype(PointerType) + +register_function_impl(pointer, rctypesobject.pointer, + revealargs = [0], + revealresult = lambda s_obj: POINTER(s_obj.controller + .ctype)) Modified: pypy/dist/pypy/rpython/controllerentry.py ============================================================================== --- pypy/dist/pypy/rpython/controllerentry.py (original) +++ pypy/dist/pypy/rpython/controllerentry.py Thu Dec 14 16:04:53 2006 @@ -10,8 +10,7 @@ def compute_result_annotation(self, *args_s): cls = self.instance controller = self.getcontroller(*args_s) - s_real_obj = controller.ctrl_new(*args_s) - return SomeControlledInstance(s_real_obj, controller) + return controller.ctrl_new(*args_s) def getcontroller(self, *args_s): return self._controller_() @@ -40,7 +39,8 @@ return True def ctrl_new(self, *args_s): - return delegate(self.new, *args_s) + s_real_obj = delegate(self.new, *args_s) + return SomeControlledInstance(s_real_obj, controller=self) def rtype_new(self, hop): r_controlled_instance = hop.r_result @@ -70,6 +70,20 @@ r_controlled_instance = hop.args_r[0] return r_controlled_instance.rtypedelegate(self.setattr, hop) + def ctrl_getitem(self, s_obj, s_key): + return delegate(self.getitem, s_obj, s_key) + + def rtype_getitem(self, hop): + r_controlled_instance = hop.args_r[0] + return r_controlled_instance.rtypedelegate(self.getitem, hop) + + def ctrl_setitem(self, s_obj, s_key, s_value): + return delegate(self.setitem, s_obj, s_key, s_value) + + def rtype_setitem(self, hop): + r_controlled_instance = hop.args_r[0] + return r_controlled_instance.rtypedelegate(self.setitem, hop) + def delegate(boundmethod, *args_s): bk = getbookkeeper() @@ -106,6 +120,15 @@ s_cin.controller.ctrl_setattr(s_cin.s_real_obj, s_attr, s_value) +class __extend__(pairtype(SomeControlledInstance, annmodel.SomeObject)): + + def getitem((s_cin, s_key)): + return s_cin.controller.ctrl_getitem(s_cin.s_real_obj, s_key) + + def setitem((s_cin, s_key), s_value): + s_cin.controller.ctrl_setitem(s_cin.s_real_obj, s_key, s_value) + + class __extend__(pairtype(SomeControlledInstance, SomeControlledInstance)): def union((s_cin1, s_cin2)): Modified: pypy/dist/pypy/rpython/rcontrollerentry.py ============================================================================== --- pypy/dist/pypy/rpython/rcontrollerentry.py (original) +++ pypy/dist/pypy/rpython/rcontrollerentry.py Thu Dec 14 16:04:53 2006 @@ -1,3 +1,4 @@ +from pypy.tool.pairtype import pairtype from pypy.objspace.flow.model import Constant from pypy.rpython.rmodel import Repr from pypy.rpython.error import TyperError @@ -41,3 +42,12 @@ def rtype_setattr(self, hop): return self.controller.rtype_setattr(hop) + + +class __extend__(pairtype(ControlledInstanceRepr, Repr)): + + def rtype_getitem((r_controlled, r_key), hop): + return r_controlled.controller.rtype_getitem(hop) + + def rtype_setitem((r_controlled, r_key), hop): + return r_controlled.controller.rtype_setitem(hop) Modified: pypy/dist/pypy/rpython/rctypes/implementation.py ============================================================================== --- pypy/dist/pypy/rpython/rctypes/implementation.py (original) +++ pypy/dist/pypy/rpython/rctypes/implementation.py Thu Dec 14 16:04:53 2006 @@ -3,6 +3,8 @@ from pypy.rpython import extregistry from pypy.rpython.extregistry import ExtRegistryEntry +DONT_IMPORT_ME + import ctypes if ctypes.__version__ < '0.9.9.6': # string comparison... good enough? raise ImportError("requires ctypes >= 0.9.9.6, got %s" % ( Modified: pypy/dist/pypy/rpython/test/test_controllerentry.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_controllerentry.py (original) +++ pypy/dist/pypy/rpython/test/test_controllerentry.py Thu Dec 14 16:04:53 2006 @@ -29,6 +29,12 @@ def set_foo(self, obj, value): value.append(obj) + def getitem(self, obj, key): + return obj + key + + def setitem(self, obj, key, value): + value.append(obj + key) + class Entry(ControllerEntry): _about_ = C _controller_ = C_Controller @@ -72,3 +78,19 @@ assert ''.join(res.chars) == "512" res = interpret(fun2, [False]) assert ''.join(res.chars) == "76542" + +def fun3(a): + lst = [] + c = C(a) + c['foo'] = lst # side-effect on lst! well, it's a test + return c['bar'], lst[0] + +def test_getsetitem_annotate(): + a = RPythonAnnotator() + s = a.build_types(fun3, [a.bookkeeper.immutablevalue("4")]) + assert s.const == ("4_bar", "4_foo") + +def test_getsetitem_specialize(): + res = interpret(fun3, ["4"]) + assert ''.join(res.item0.chars) == "4_bar" + assert ''.join(res.item1.chars) == "4_foo" From antocuni at codespeak.net Thu Dec 14 16:16:39 2006 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Thu, 14 Dec 2006 16:16:39 +0100 (CET) Subject: [pypy-svn] r35744 - in pypy/dist/pypy/translator: cli oosupport Message-ID: <20061214151639.5F1F810075@code0.codespeak.net> Author: antocuni Date: Thu Dec 14 16:16:38 2006 New Revision: 35744 Modified: pypy/dist/pypy/translator/cli/function.py pypy/dist/pypy/translator/cli/metavm.py pypy/dist/pypy/translator/oosupport/function.py Log: Added a generic way to get unique labels inside a function, a some refactoring to use it. Modified: pypy/dist/pypy/translator/cli/function.py ============================================================================== --- pypy/dist/pypy/translator/cli/function.py (original) +++ pypy/dist/pypy/translator/cli/function.py Thu Dec 14 16:16:38 2006 @@ -58,16 +58,8 @@ self._setup_link(link) class LastExceptionHandler(object): - catch_label_count = 0 in_try = False - def next_catch_label(self): - self.catch_label_count += 1 - return self.catch_label() - - def catch_label(self): - return '__catch_%d' % self.catch_label_count - def begin_try(self): self.in_try = True self.ilasm.opcode('// begin_try') @@ -79,16 +71,16 @@ self.in_try = False def begin_catch(self, llexitcase): - self.ilasm.label(self.catch_label()) + self.ilasm.label(self.current_label('catch')) ll_meta_exc = llexitcase ll_exc = ll_meta_exc._inst.class_._INSTANCE cts_exc = self.cts.lltype_to_cts(ll_exc, False) self.ilasm.opcode('ldsfld', 'object last_exception') self.isinstance(cts_exc) self.ilasm.opcode('dup') - self.ilasm.opcode('brtrue.s', 6) # ?? + self.ilasm.opcode('brtrue.s', 6) self.ilasm.opcode('pop') - self.ilasm.opcode('br', self.next_catch_label()) + self.ilasm.opcode('br', self.next_label('catch')) # here is the target of the above brtrue.s self.ilasm.opcode('ldnull') self.ilasm.opcode('stsfld', 'object last_exception') @@ -113,6 +105,10 @@ self.store(link.last_exc_value) self._setup_link(link) + def before_last_blocks(self): + self.ilasm.label(self.current_label('catch')) + self.ilasm.opcode('nop') + def render_raise_block(self, block): exc = block.inputargs[1] self.load(exc) @@ -169,13 +165,6 @@ class Function(ExceptionHandler, OOFunction, Node, CLIBaseGenerator): - def next_catch_label(self): - self.catch_label_count += 1 - return self.catch_label() - - def catch_label(self): - return '__catch_%d' % self.catch_label_count - def __init__(self, *args, **kwargs): OOFunction.__init__(self, *args, **kwargs) self._set_args() @@ -202,13 +191,6 @@ self.ilasm.begin_function(self.name, args, returntype, self.is_entrypoint, meth_type) self.ilasm.locals(self.locals) - def before_last_blocks(self): - # This is only executed when using LastExceptionHandler. - # Need to be deleted when we will use a saner approach. - if hasattr(self, 'catch_label'): - self.ilasm.label(self.catch_label()) - self.ilasm.opcode('nop') - def end_render(self): self.ilasm.end_function() Modified: pypy/dist/pypy/translator/cli/metavm.py ============================================================================== --- pypy/dist/pypy/translator/cli/metavm.py (original) +++ pypy/dist/pypy/translator/cli/metavm.py Thu Dec 14 16:16:38 2006 @@ -154,7 +154,8 @@ self.mapping = mapping def render(self, generator, op): - if hasattr(self, 'catch_label'): + from pypy.translator.cli.function import LastExceptionHandler + if isinstance(generator, LastExceptionHandler): self.render_last(generator, op) else: self.render_native(generator, op) Modified: pypy/dist/pypy/translator/oosupport/function.py ============================================================================== --- pypy/dist/pypy/translator/oosupport/function.py (original) +++ pypy/dist/pypy/translator/oosupport/function.py Thu Dec 14 16:16:38 2006 @@ -3,6 +3,7 @@ from pypy.translator.oosupport.metavm import InstructionList class Function(object): + def __init__(self, db, graph, name = None, is_method = False, is_entrypoint = False): self.db = db self.cts = db.genoo.TypeSystem(db) @@ -11,12 +12,22 @@ self.is_method = is_method self.is_entrypoint = is_entrypoint self.generator = None # set in render() + self.label_counters = {} # If you want to enumerate args/locals before processing, then # add these functions into your __init__() [they are defined below] # self._set_args() # self._set_locals() + def current_label(self, prefix='label'): + current = self.label_counters.get(prefix, 0) + return '__%s_%d' % (prefix, current) + + def next_label(self, prefix='label'): + current = self.label_counters.get(prefix, 0) + self.label_counters[prefix] = current+1 + return self.current_label(prefix) + def get_name(self): return self.name From ac at codespeak.net Thu Dec 14 16:53:37 2006 From: ac at codespeak.net (ac at codespeak.net) Date: Thu, 14 Dec 2006 16:53:37 +0100 (CET) Subject: [pypy-svn] r35749 - pypy/dist/pypy/module/pypyjit Message-ID: <20061214155337.50FCC10076@code0.codespeak.net> Author: ac Date: Thu Dec 14 16:53:36 2006 New Revision: 35749 Modified: pypy/dist/pypy/module/pypyjit/interp_jit.py Log: Remove too verbose print Modified: pypy/dist/pypy/module/pypyjit/interp_jit.py ============================================================================== --- pypy/dist/pypy/module/pypyjit/interp_jit.py (original) +++ pypy/dist/pypy/module/pypyjit/interp_jit.py Thu Dec 14 16:53:36 2006 @@ -74,7 +74,6 @@ def dispatch_bytecode(self, co_code, next_instr, ec): if self.pycode.jit_enable: - print "jitting:", self.pycode.co_name return self.dispatch_jit(co_code, next_instr, ec) else: return super_dispatch_bytecode(self, co_code, next_instr, ec) From ac at codespeak.net Thu Dec 14 16:57:56 2006 From: ac at codespeak.net (ac at codespeak.net) Date: Thu, 14 Dec 2006 16:57:56 +0100 (CET) Subject: [pypy-svn] r35750 - pypy/dist/pypy/translator/goal Message-ID: <20061214155756.E1B1310083@code0.codespeak.net> Author: ac Date: Thu Dec 14 16:57:56 2006 New Revision: 35750 Modified: pypy/dist/pypy/translator/goal/richards.py Log: Make richards use the jit if it is there. Modified: pypy/dist/pypy/translator/goal/richards.py ============================================================================== --- pypy/dist/pypy/translator/goal/richards.py (original) +++ pypy/dist/pypy/translator/goal/richards.py Thu Dec 14 16:57:56 2006 @@ -413,6 +413,20 @@ print "Total time for %d iterations: %.2f secs" %(iterations,total_s) print "Average time per iteration: %.2f ms" %(total_s*1000/iterations) +try: + import pypyjit +except ImportError: + pass +else: + import types + for item in globals().values(): + if isinstance(item, types.FunctionType): + pypyjit.enable(item.func_code) + elif isinstance(item, type): + for it in item.__dict__.values(): + if isinstance(it, types.FunctionType): + pypyjit.enable(it.func_code) + if __name__ == '__main__': import sys if len(sys.argv) >= 2: From arigo at codespeak.net Thu Dec 14 17:17:26 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 14 Dec 2006 17:17:26 +0100 (CET) Subject: [pypy-svn] r35751 - pypy/dist/pypy/module/_stackless Message-ID: <20061214161726.D79EC10088@code0.codespeak.net> Author: arigo Date: Thu Dec 14 17:17:25 2006 New Revision: 35751 Modified: pypy/dist/pypy/module/_stackless/interp_greenlet.py Log: Translation fixes in interp_greenlet. Modified: pypy/dist/pypy/module/_stackless/interp_greenlet.py ============================================================================== --- pypy/dist/pypy/module/_stackless/interp_greenlet.py (original) +++ pypy/dist/pypy/module/_stackless/interp_greenlet.py Thu Dec 14 17:17:25 2006 @@ -64,10 +64,9 @@ def descr_method__init__(self, w_run=NoneNotWrapped, w_parent=NoneNotWrapped): if w_run is not None: - self.w_set_run.im_func(self.space, self, w_run) + self.set_run(w_run) if w_parent is not None: - self.w_set_parent.im_func(self.space, self, w_parent) - # XXX strange style above, GetSetProperty needs a cleanup + self.set_parent(w_parent) def _get_state(space): return space.fromcache(AppGreenletCoState) @@ -156,7 +155,7 @@ raise OperationError(space.w_AttributeError, space.wrap("run")) return w_run - def w_set_run(space, self, w_run): + def set_run(self, w_run): space = self.space if self.thunk is None: raise OperationError(space.w_AttributeError, @@ -164,6 +163,9 @@ "after the start of the greenlet")) self.w_callable = w_run + def w_set_run(space, self, w_run): + self.set_run(w_run) + def w_del_run(space, self): if self.w_callable is None: raise OperationError(space.w_AttributeError, space.wrap("run")) @@ -172,7 +174,8 @@ def w_get_parent(space, self): return space.wrap(self.parent) - def w_set_parent(space, self, w_parent): + def set_parent(self, w_parent): + space = self.space newparent = space.interp_w(AppGreenlet, w_parent) if newparent.costate is not self.costate: raise OperationError(self.costate.w_GreenletError, @@ -185,6 +188,9 @@ curr = curr.parent self.parent = newparent + def w_set_parent(space, self, w_parent): + self.set_parent(w_parent) + def w_get_frame(space, self): if not self.active or self.costate.current is self: f = None From antocuni at codespeak.net Thu Dec 14 17:23:58 2006 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Thu, 14 Dec 2006 17:23:58 +0100 (CET) Subject: [pypy-svn] r35752 - in pypy/dist/pypy/translator: cli cli/test oosupport Message-ID: <20061214162358.6E64E1007F@code0.codespeak.net> Author: antocuni Date: Thu Dec 14 17:23:57 2006 New Revision: 35752 Added: pypy/dist/pypy/translator/cli/test/test_backendopt.py (contents, props changed) Modified: pypy/dist/pypy/translator/cli/function.py pypy/dist/pypy/translator/cli/ilgenerator.py pypy/dist/pypy/translator/cli/test/runtest.py pypy/dist/pypy/translator/oosupport/function.py Log: Now gencli (partially) supports the graphs produced by merge_if_blocks. Modified: pypy/dist/pypy/translator/cli/function.py ============================================================================== --- pypy/dist/pypy/translator/cli/function.py (original) +++ pypy/dist/pypy/translator/cli/function.py Thu Dec 14 17:23:57 2006 @@ -5,6 +5,7 @@ from pypy.objspace.flow import model as flowmodel from pypy.rpython.lltypesystem.lltype import Void +from pypy.rpython.ootypesystem import ootype from pypy.translator.oosupport.function import Function as OOFunction from pypy.translator.cli.option import getoption from pypy.translator.cli.cts import CTS @@ -203,6 +204,39 @@ self.load(return_var) self.ilasm.opcode('ret') + def render_numeric_switch(self, block): + cases = {} + for link in block.exits: + if link.exitcase == "default": + default = link, self.next_label('switch') + else: + if block.exitswitch.concretetype in (ootype.Char, ootype.UniChar): + value = ord(link.exitcase) + else: + value = link.exitcase + assert value >= 0 + cases[value] = link, self.next_label('switch') + + max_case = max(cases.keys()) + if max_case > 4096: # XXX: how to find a good way to determine whether to use switch? + raise NotImplementedError # TODO + + targets = [] + for i in xrange(max_case+1): + link, lbl = cases.get(i, default) + targets.append(lbl) + self.generator.load(block.exitswitch) + self.ilasm.switch(targets) + self.render_switch_case(*default) + for link, lbl in cases.itervalues(): + self.render_switch_case(link, lbl) + + def render_switch_case(self, link, label): + target_label = self._get_block_name(link.target) + self.set_label(label) + self._setup_link(link) + self.generator.branch_unconditionally(target_label) + # Those parts of the generator interface that are function # specific Modified: pypy/dist/pypy/translator/cli/ilgenerator.py ============================================================================== --- pypy/dist/pypy/translator/cli/ilgenerator.py (original) +++ pypy/dist/pypy/translator/cli/ilgenerator.py Thu Dec 14 17:23:57 2006 @@ -8,7 +8,7 @@ from pypy.translator.cli.support import string_literal def isnan(v): - return v != v*1.0 or (v == 1.0 and v == 2.0) + return v != v*1.0 or (v == 1.0 and v == 2.0) def isinf(v): return v!=0 and (v == v*2) @@ -211,6 +211,10 @@ def load_local(self,v): self.opcode('ldloc', repr(v.name)) + def switch(self, targets): + cmd = 'switch(%s)' % ', '.join(targets) + self.opcode(cmd) + def load_const(self,type_,v): if type_ is Void: pass Modified: pypy/dist/pypy/translator/cli/test/runtest.py ============================================================================== --- pypy/dist/pypy/translator/cli/test/runtest.py (original) +++ pypy/dist/pypy/translator/cli/test/runtest.py Thu Dec 14 17:23:57 2006 @@ -9,6 +9,7 @@ from pypy.rpython.lltypesystem.lltype import typeOf from pypy.rpython.ootypesystem import ootype from pypy.annotation.model import lltype_to_annotation +from pypy.translator.backendopt.all import backend_optimizations from pypy.translator.cli.option import getoption from pypy.translator.cli.gencli import GenCli @@ -134,15 +135,15 @@ assert False, 'Input type %s not supported' % arg_type -def compile_function(func, annotation=[], graph=None): +def compile_function(func, annotation=[], graph=None, backend_opt={}): olddefs = patch() - gen = _build_gen(func, annotation, graph) + gen = _build_gen(func, annotation, graph, backend_opt) gen.generate_source() exe_name = gen.build_exe() unpatch(*olddefs) # restore original values return CliFunctionWrapper(exe_name) -def _build_gen(func, annotation, graph=None): +def _build_gen(func, annotation, graph=None, backend_opt={}): try: func = func.im_func except AttributeError: @@ -162,7 +163,16 @@ t.view() t.buildrtyper(type_system="ootype").specialize() - + backend_opt_default = dict( + raisingop2direct_call=False, + inline_threshold=0, + mallocs=False, + merge_if_blocks=False, + constfold=True, + heap2stack=False, + clever_malloc_removal=False) + backend_opt_default.update(backend_opt) + backend_optimizations(t, **backend_opt_default) main_graph = t.graphs[0] Added: pypy/dist/pypy/translator/cli/test/test_backendopt.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/translator/cli/test/test_backendopt.py Thu Dec 14 17:23:57 2006 @@ -0,0 +1,22 @@ +import py +from pypy.translator.cli.test.runtest import compile_function +from pypy.translator.c.test.test_backendoptimized import \ + TestTypedOptimizedSwitchTestCase as c_TestTypedOptimizedSwitchTestCase + +class CTestCompat: + backend_opt = { + 'merge_if_blocks': True + } + + def CodeGenerator(self): + return self + + def getcompiled(self, fn, annotation): + return compile_function(fn, annotation, backend_opt=self.backend_opt) + +class TestOptimizedSwitchTestCase(CTestCompat, c_TestTypedOptimizedSwitchTestCase): + def test_longlong_switch(self): + py.test.skip('Not yet supported') + + def test_ulonglong_switch(self): + py.test.skip('Not yet supported') Modified: pypy/dist/pypy/translator/oosupport/function.py ============================================================================== --- pypy/dist/pypy/translator/oosupport/function.py (original) +++ pypy/dist/pypy/translator/oosupport/function.py Thu Dec 14 17:23:57 2006 @@ -1,5 +1,5 @@ from pypy.objspace.flow import model as flowmodel -from pypy.rpython.ootypesystem.ootype import Void +from pypy.rpython.ootypesystem import ootype from pypy.translator.oosupport.metavm import InstructionList class Function(object): @@ -166,26 +166,42 @@ raise NotImplementedError def render_normal_block(self, block): - # renders all ops but the last one for op in block.operations: self._render_op(op) + if block.exitswitch is None: + assert len(block.exits) == 1 + link = block.exits[0] + target_label = self._get_block_name(link.target) + self._setup_link(link) + self.generator.branch_unconditionally(target_label) + elif block.exitswitch.concretetype is ootype.Bool: + self.render_bool_switch(block) + elif block.exitswitch.concretetype in (ootype.Signed, ootype.Unsigned, ootype.Char, ootype.UniChar): + self.render_numeric_switch(block) + else: + assert False, 'Unknonw exitswitch type: %s' % block.exitswitch.concretetype + + def render_bool_switch(self, block): for link in block.exits: self._setup_link(link) target_label = self._get_block_name(link.target) - if link.exitcase is None or link is block.exits[-1]: + if link is block.exits[-1]: self.generator.branch_unconditionally(target_label) else: - assert type(link.exitcase is bool) + assert type(link.exitcase) is bool assert block.exitswitch is not None self.generator.load(block.exitswitch) self.generator.branch_conditionally(link.exitcase, target_label) + def render_numeric_switch(self, block): + raise NotImplementedError # it's too dependent on the backend to be implemented here + def _setup_link(self, link): self.generator.add_comment("Setup link") target = link.target for to_load, to_store in zip(link.args, target.inputargs): - if to_load.concretetype is not Void: + if to_load.concretetype is not ootype.Void: self.generator.add_comment(" to_load=%r to_store=%r" % ( to_load, to_store)) self.generator.load(to_load) @@ -247,13 +263,13 @@ seen = {} for v in mix: is_var = isinstance(v, flowmodel.Variable) - if id(v) not in seen and is_var and v.name not in args and v.concretetype is not Void: + if id(v) not in seen and is_var and v.name not in args and v.concretetype is not ootype.Void: locals.append(self.cts.llvar_to_cts(v)) seen[id(v)] = True self.locals = locals def _set_args(self): - args = [arg for arg in self.graph.getargs() if arg.concretetype is not Void] + args = [arg for arg in self.graph.getargs() if arg.concretetype is not ootype.Void] self.args = map(self.cts.llvar_to_cts, args) self.argset = set([argname for argtype, argname in self.args]) From arigo at codespeak.net Thu Dec 14 17:26:48 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 14 Dec 2006 17:26:48 +0100 (CET) Subject: [pypy-svn] r35753 - pypy/dist/pypy/rpython/rctypes Message-ID: <20061214162648.2884B1007F@code0.codespeak.net> Author: arigo Date: Thu Dec 14 17:26:47 2006 New Revision: 35753 Added: pypy/dist/pypy/rpython/rctypes/implementation.py - copied unchanged from r35742, pypy/dist/pypy/rpython/rctypes/implementation.py Log: I didn't mean to check this in. From adim at codespeak.net Thu Dec 14 17:28:11 2006 From: adim at codespeak.net (adim at codespeak.net) Date: Thu, 14 Dec 2006 17:28:11 +0100 (CET) Subject: [pypy-svn] r35754 - in pypy/branch/ast-experiments/pypy: interpreter interpreter/pyparser interpreter/pyparser/test interpreter/stablecompiler module/recparser Message-ID: <20061214162811.2CC271008A@code0.codespeak.net> Author: adim Date: Thu Dec 14 17:28:05 2006 New Revision: 35754 Added: pypy/branch/ast-experiments/pypy/interpreter/pyparser/test/expressions.py Modified: pypy/branch/ast-experiments/pypy/interpreter/pycompiler.py pypy/branch/ast-experiments/pypy/interpreter/pyparser/astbuilder.py pypy/branch/ast-experiments/pypy/interpreter/pyparser/ebnfparse.py pypy/branch/ast-experiments/pypy/interpreter/pyparser/pythonparse.py pypy/branch/ast-experiments/pypy/interpreter/pyparser/pythonutil.py pypy/branch/ast-experiments/pypy/interpreter/pyparser/test/test_astbuilder.py pypy/branch/ast-experiments/pypy/interpreter/pyparser/test/test_astcompiler.py pypy/branch/ast-experiments/pypy/interpreter/pyparser/test/test_samples.py pypy/branch/ast-experiments/pypy/interpreter/stablecompiler/transformer.py pypy/branch/ast-experiments/pypy/module/recparser/pyparser.py Log: small pyparser refactorings - removed some unused code - eased a bit python parser creation (build_parser / get_pyparser) Modified: pypy/branch/ast-experiments/pypy/interpreter/pycompiler.py ============================================================================== --- pypy/branch/ast-experiments/pypy/interpreter/pycompiler.py (original) +++ pypy/branch/ast-experiments/pypy/interpreter/pycompiler.py Thu Dec 14 17:28:05 2006 @@ -205,15 +205,15 @@ from pypy.interpreter.astcompiler.pycodegen import InteractiveCodeGenerator from pypy.interpreter.astcompiler.pycodegen import ExpressionCodeGenerator from pypy.interpreter.astcompiler.ast import Node - from pyparser.pythonutil import AstBuilder, PYTHON_PARSER, TARGET_DICT + from pyparser.astbuilder import AstBuilder + from pyparser.pythonparse import PYTHON_PARSER from pypy.interpreter.pycode import PyCode flags |= stdlib___future__.generators.compiler_flag # always on (2.2 compat) space = self.space try: builder = AstBuilder(space=space) - target_rule = TARGET_DICT[mode] - PYTHON_PARSER.parse_source(source, target_rule, builder, flags) + PYTHON_PARSER.parse_source(source, mode, builder, flags) ast_tree = builder.rule_stack[-1] encoding = builder.source_encoding except SyntaxError, e: Modified: pypy/branch/ast-experiments/pypy/interpreter/pyparser/astbuilder.py ============================================================================== --- pypy/branch/ast-experiments/pypy/interpreter/pyparser/astbuilder.py (original) +++ pypy/branch/ast-experiments/pypy/interpreter/pyparser/astbuilder.py Thu Dec 14 17:28:05 2006 @@ -10,10 +10,6 @@ from pypy.interpreter.pyparser.error import SyntaxError from pypy.interpreter.pyparser.parsestring import parsestr -sym = pythonparse.PYTHON_PARSER.symbols - -DEBUG_MODE = 0 - # XXX : use builder.parser instead sym = pythonparse.PYTHON_PARSER.symbols rsym = pythonparse.PYTHON_PARSER.symbol_repr @@ -1698,8 +1694,9 @@ if self.with_enabled: return self.with_enabled = True - self.keywords.update({'with':None, 'as': None}) - + # XXX + # self.keywords.update({'with':None, 'as': None}) + def context(self): return AstBuilderContext(self.rule_stack) Modified: pypy/branch/ast-experiments/pypy/interpreter/pyparser/ebnfparse.py ============================================================================== --- pypy/branch/ast-experiments/pypy/interpreter/pyparser/ebnfparse.py (original) +++ pypy/branch/ast-experiments/pypy/interpreter/pyparser/ebnfparse.py Thu Dec 14 17:28:05 2006 @@ -5,7 +5,6 @@ from ebnflexer import GrammarSource import ebnfgrammar from ebnfgrammar import GRAMMAR_GRAMMAR -from syntaxtree import AbstractSyntaxVisitor ORDA = ord("A") @@ -21,14 +20,14 @@ return False v = ord(name[0]) if not (ORDA <= v <= ORDZ or - ORDa <= v <= ORDz or v == ORD_ ): + ORDa <= v <= ORDz or v == ORD_): return False for c in name: v = ord(c) if not (ORDA <= v <= ORDZ or ORDa <= v <= ORDz or ORD0 <= v <= ORD9 or - v == ORD_ ): + v == ORD_): return False return True @@ -41,21 +40,16 @@ '%', '<<', '//', '\\', '', '\n\\)', '\\(', ';', ':', '@', '\\[', '\\]', '`', '\\{', '\\}'] - - - TERMINALS = [ 'NAME', 'NUMBER', 'STRING', 'NEWLINE', 'ENDMARKER', 'INDENT', 'DEDENT' ] -## Grammar Visitors ################################################## # FIXME: parsertools.py ? parser/__init__.py ? - class NameToken(Token): """A token that is not a keyword""" - def __init__(self, parser, keywords=None ): - Token.__init__(self, parser, parser.tokens['NAME'] ) + def __init__(self, parser, keywords=None): + Token.__init__(self, parser, parser.tokens['NAME']) self.keywords = keywords def match(self, source, builder, level=0): @@ -69,7 +63,6 @@ else: # error unknown or negative integer """ - ctx = source.context() tk = source.next() if tk.codename == self.codename: @@ -81,6 +74,7 @@ source.restore( ctx ) return 0 + def match_token(self, builder, other): """special case of match token for tokens which are really keywords """ @@ -97,11 +91,17 @@ return True +class EBNFBuilderContext(AbstractContext): + def __init__(self, stackpos, seqcounts, altcounts): + self.stackpos = stackpos + self.seqcounts = seqcounts + self.altcounts = altcounts + class EBNFBuilder(AbstractBuilder): """Build a grammar tree""" - def __init__(self, gram_parser, dest_parser ): - AbstractBuilder.__init__(self, dest_parser ) + def __init__(self, gram_parser, dest_parser): + AbstractBuilder.__init__(self, dest_parser) self.gram = gram_parser self.rule_stack = [] self.seqcounts = [] # number of items in the current sequence @@ -114,8 +114,17 @@ self.tokens = {} self.keywords = [] NAME = dest_parser.add_token('NAME') + # NAME = dest_parser.tokens['NAME'] self.tokens[NAME] = NameToken(dest_parser, keywords=self.keywords) + def context(self): + return EBNFBuilderContext(len(self.rule_stack), self.seqcounts, self.altcounts) + + def restore(self, ctx): + del self.rule_stack[ctx.stackpos:] + self.seqcounts = ctx.seqcounts + self.altcounts = ctx.altcounts + def new_symbol(self): """Allocate and return a new (anonymous) grammar symbol whose name is based on the current grammar rule being parsed""" @@ -169,14 +178,6 @@ self.parser.root_rules[codename] = proxy return proxy - def context(self): - """Return an opaque context object""" - return None - - def restore(self, ctx): - """Accept an opaque context object""" - assert False, "Not supported" - def alternative(self, rule, source): return True @@ -190,7 +191,6 @@ def sequence(self, rule, source, elts_number): _rule = rule.codename if _rule == self.gram.sequence: -# print " -sequence", self.curaltcount, self.curseqcount if self.curseqcount==1: self.curseqcount = 0 self.curaltcount += 1 @@ -201,7 +201,6 @@ self.curseqcount = 0 self.curaltcount += 1 elif _rule == self.gram.alternative: -# print " -alternative", self.curaltcount, self.curseqcount if self.curaltcount == 1: self.curaltcount = 0 return True @@ -210,17 +209,14 @@ self.rule_stack.append( new_rule ) self.curaltcount = 0 elif _rule == self.gram.group: -# print " -group", self.curaltcount, self.curseqcount self.curseqcount += 1 elif _rule == self.gram.option: -# print " -option", self.curaltcount, self.curseqcount # pops the last alternative rules = self.pop_rules( 1 ) new_rule = self.parser.KleeneStar( self.new_symbol(), _min=0, _max=1, rule=rules[0] ) self.rule_stack.append( new_rule ) self.curseqcount += 1 elif _rule == self.gram.rule: -# print " -rule", self.curaltcount, self.curseqcount assert len(self.rule_stack)==1 old_rule = self.rule_stack[0] del self.rule_stack[0] @@ -235,7 +231,6 @@ return True def token(self, name, value, source): -# print "token", name, value if name == self.gram.TOK_STRING: self.handle_TOK_STRING( name, value ) self.curseqcount += 1 @@ -292,35 +287,16 @@ self.rule_stack.append(tok) -def parse_grammar_text( parser, txt): - """parses a grammar input - - stream : file-like object representing the grammar to parse - """ - source = GrammarSource( GRAMMAR_GRAMMAR, txt) - builder = EBNFBuilder(GRAMMAR_GRAMMAR, dest_parser=parser ) - result = GRAMMAR_GRAMMAR.root_rules['grammar'].match(source, builder) - builder.resolve_rules() - parser.build_first_sets() - return parser - -def target_parse_grammar_text(txt): - vis = parse_grammar_text(txt) - # do nothing - return None - -def main_build(): - from pprint import pprint - grambuild = parse_grammar(file('data/Grammar2.3')) - for i,r in enumerate(grambuild.items): - print "% 3d : %s" % (i, r) - pprint(grambuild.terminals.keys()) - pprint(grambuild.tokens) - print "|".join(grambuild.tokens.keys() ) - -def main_build(): - import sys - return parse_grammar_text( file(sys.argv[-1]).read() ) -if __name__ == "__main__": - result = main_build() +## # XXX: parser method ? +## def parse_grammar_text(parser, txt): +## """parses a grammar input + +## txt : the grammar definition +## """ +## source = GrammarSource(GRAMMAR_GRAMMAR, txt) +## builder = EBNFBuilder(GRAMMAR_GRAMMAR, dest_parser=parser) +## result = GRAMMAR_GRAMMAR.root_rules['grammar'].match(source, builder) +## builder.resolve_rules() +## parser.build_first_sets() +## return parser Modified: pypy/branch/ast-experiments/pypy/interpreter/pyparser/pythonparse.py ============================================================================== --- pypy/branch/ast-experiments/pypy/interpreter/pyparser/pythonparse.py (original) +++ pypy/branch/ast-experiments/pypy/interpreter/pyparser/pythonparse.py Thu Dec 14 17:28:05 2006 @@ -17,64 +17,18 @@ import pypy.interpreter.pyparser.pytoken as pytoken import pypy.interpreter.pyparser.ebnfparse as ebnfparse import pypy.interpreter.pyparser.grammar as grammar +from pypy.interpreter.pyparser.pythonutil import build_parser_for_version -try: - from pypy.interpreter.pyparser import symbol -except ImportError: - # for standalone testing - import symbol +# try: +from pypy.interpreter.pyparser import symbol +# except ImportError: +# # for standalone testing +# import symbol from codeop import PyCF_DONT_IMPLY_DEDENT -class AlternateGrammarException(Exception): - pass - -class PythonParser(grammar.Parser): - """Wrapper class for python grammar""" - def __init__(self): - grammar.Parser.__init__(self) - # XXX (adim): this is trunk's keyword management - # self.with_grammar = None - # self.keywords = dict.fromkeys(grammar_builder.keywords) - # # Only when with_statement is enabled - # self.keywords.pop('with', None) - # self.keywords.pop('as', None) - - def parse_source(self, textsrc, goal, builder, flags=0): - """Parse a python source according to goal""" - # Detect source encoding. - if textsrc[:3] == '\xEF\xBB\xBF': - textsrc = textsrc[3:] - enc = 'utf-8' - else: - enc = _normalize_encoding(_check_for_encoding(textsrc)) - if enc is not None and enc not in ('utf-8', 'iso-8859-1'): - textsrc = recode_to_utf8(builder.space, textsrc, enc) - - lines = [line + '\n' for line in textsrc.split('\n')] - builder.source_encoding = enc - if len(textsrc) and textsrc[-1] == '\n': - lines.pop() - flags &= ~PyCF_DONT_IMPLY_DEDENT - return self.parse_lines(lines, goal, builder, flags) - - - def parse_lines(self, lines, goal, builder, flags=0): - # XXX (adim): this is trunk's keyword management - # builder.keywords = self.keywords.copy() - # if flags & CO_FUTURE_WITH_STATEMENT: - # builder.enable_with() - goalnumber = self.symbols[goal] - target = self.root_rules[goalnumber] - src = Source(self, lines, flags) - - if not target.match(src, builder): - line, lineno = src.debug() - # XXX needs better error messages - raise SyntaxError("invalid syntax", lineno, -1, line) - # return None - return builder +## files encoding management ############################################ _recode_to_utf8 = gateway.applevel(r''' def _recode_to_utf8(text, encoding): return unicode(text, encoding).encode("utf-8") @@ -115,6 +69,7 @@ return _check_line_for_encoding(s[eol + 1:]) return _check_line_for_encoding(s[eol + 1:eol2]) + def _check_line_for_encoding(line): """returns the declared encoding or None""" i = 0 @@ -125,138 +80,99 @@ return None return match_encoding_declaration(line[i:]) -PYTHON_VERSION = ".".join([str(i) for i in sys.version_info[:2]]) -def get_grammar_file( version ): - """returns the python grammar corresponding to our CPython version""" - if version == "native": - _ver = PYTHON_VERSION - elif version == "stable": - _ver = "_stablecompiler" - elif version in ("2.3","2.4","2.5a"): - _ver = version - return os.path.join( os.path.dirname(__file__), "data", "Grammar" + _ver ), _ver -# unfortunately the command line options are not parsed yet -PYTHON_GRAMMAR, PYPY_VERSION = get_grammar_file( Options.version ) +## Python Source Parser ################################################### +class AlternateGrammarException(Exception): + pass +class PythonParser(grammar.Parser): + """Wrapper class for python grammar""" + targets = { + 'eval' : "eval_input", + 'single' : "single_input", + 'exec' : "file_input", + } + + def __init__(self, predefined_symbols=None): + grammar.Parser.__init__(self) + pytoken.setup_tokens(self) + if predefined_symbols: + self.load_symbols(predefined_symbols) + + # XXX (adim): this is trunk's keyword management + # self.with_grammar = None + # self.keywords = dict.fromkeys(grammar_builder.keywords) + # # Only when with_statement is enabled + # self.keywords.pop('with', None) + # self.keywords.pop('as', None) + + def parse_source(self, textsrc, mode, builder, flags=0): + """Parse a python source according to goal""" + goal = self.targets[mode] + # Detect source encoding. + if textsrc[:3] == '\xEF\xBB\xBF': + textsrc = textsrc[3:] + enc = 'utf-8' + else: + enc = _normalize_encoding(_check_for_encoding(textsrc)) + if enc is not None and enc not in ('utf-8', 'iso-8859-1'): + textsrc = recode_to_utf8(builder.space, textsrc, enc) -def load_python_grammar(fname): - """Loads the grammar using the 'dynamic' rpython parser""" - _grammar_file = file(fname) - parser = PYTHON_PARSER - # populate symbols - ebnfparse.parse_grammar_text( parser, file(fname).read() ) - return parser - -debug_print( "Loading grammar %s" % PYTHON_GRAMMAR ) -PYTHON_PARSER = PythonParser() -# print "sym_name ===>", symbol.sym_name -PYTHON_PARSER.load_symbols( symbol.sym_name ) -# debug_print( "Loading grammar %s" % PYTHON_GRAMMAR ) -# PYTHON_PARSER = python_grammar( PYTHON_GRAMMAR) -#PYTHON_PARSER.with_grammar = python_grammar( PYTHON_GRAMMAR + '_with' ) - -def reload_grammar(version): - """helper function to test with pypy different grammars""" - global PYTHON_GRAMMAR, PYTHON_PARSER, PYPY_VERSION - PYTHON_GRAMMAR, PYPY_VERSION = get_grammar_file( version ) - debug_print( "Reloading grammar %s" % PYTHON_GRAMMAR ) - PYTHON_PARSER = python_grammar( PYTHON_GRAMMAR ) - -def parse_file_input(pyf, gram, builder ): - """Parse a python file""" - return gram.parse_source( pyf.read(), "file_input", builder ) - -def parse_single_input(textsrc, gram, builder ): - """Parse a python single statement""" - return gram.parse_source( textsrc, "single_input", builder ) - -def parse_eval_input(textsrc, gram, builder): - """Parse a python expression""" - return gram.parse_source( textsrc, "eval_input", builder ) - -def grammar_rules( space ): - w_rules = space.newdict() - for key, value in PYTHON_PARSER.rules.iteritems(): - space.setitem(w_rules, space.wrap(key), space.wrap(value)) - return w_rules - -def dot_node( gen, rule_name, rule, symbols, edges, count ): - from pypy.interpreter.pyparser.grammar import KleeneStar, Sequence, Alternative, Token - subrule_name = symbols.get( rule.codename, rule.codename ) - label = None - if not subrule_name.startswith(":"+rule_name): - node_name = rule_name + "_ext_" + str(count[0]) - count[0]+=1 - label = subrule_name - gen.emit_node( node_name, shape="parallelogram", label=subrule_name ) - edges.append( (node_name, subrule_name) ) - return node_name - subrule_name = subrule_name.replace(":","_") - if isinstance(rule, KleeneStar): - node = dot_node( gen, rule_name, rule.args[0], symbols, edges, count ) - gen.emit_edge( node, node, label=rule.get_star(), style='solid' ) - return node - elif isinstance(rule, Sequence): - gen.enter_subgraph( subrule_name ) - first_node = None - for n in rule.args: - node_name = dot_node( gen, rule_name, n, symbols, edges, count ) - if first_node: - gen.emit_edge( first_node, node_name, style='solid' ) - first_node = node_name - gen.leave_subgraph() - return subrule_name - elif isinstance(rule, Alternative): - gen.enter_subgraph( subrule_name ) - for n in rule.args: - node_name = dot_node( gen, rule_name, n, symbols, edges, count ) - gen.leave_subgraph() - return subrule_name - elif isinstance(rule, Token): - node_name = rule_name + "_ext_" + str(count[0]) - count[0]+=1 - gen.emit_node( node_name, shape='box', label=rule.display( 0, symbols ) ) - return node_name - raise RuntimeError("Unknown node type") - -def gen_grammar_dot( name, root_rules, rules, symbols ): - """Quick hack to output a dot graph of the grammar""" - from pypy.translator.tool.make_dot import DotGen - gen = DotGen(name) - edges = [] - count = [0] - for r in root_rules: - rule_name = symbols.get( r.codename, r.codename ) - gen.emit_node( rule_name, shape='hexagon', label=r.display(0,symbols) ) - for rule in r.args: - node = dot_node( gen, rule_name, rule, symbols, edges, count ) - gen.emit_edge( rule_name, node, style='solid' ) - for left, right in edges: - gen.emit_edge( left, right, style='solid' ) - gen.generate(target='ps') - - -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 ) - -## debug_print( "Loading grammar %s" % PYTHON_GRAMMAR ) -## PYTHON_PARSER = PythonParser() -## PYTHON_PARSER.load_symbols( symbol.sym_name ) -pytoken.setup_tokens( PYTHON_PARSER ) -load_python_grammar( PYTHON_GRAMMAR ) -#PYTHON_PARSER.with_grammar = python_grammar( PYTHON_GRAMMAR + '_with' ) - -def make_rule( space, w_rule ): - rule = space.str_w( w_rule ) - -if __name__=="__main__": - symbols = {} - symbols.update( pytoken.tok_name ) - symbols.update( pysymbol._cpython_symbols.sym_name ) - gen_grammar_dot("grammar", PYTHON_PARSER.rules.values(), PYTHON_PARSER.items, symbols ) + lines = [line + '\n' for line in textsrc.split('\n')] + builder.source_encoding = enc + if len(textsrc) and textsrc[-1] == '\n': + lines.pop() + flags &= ~PyCF_DONT_IMPLY_DEDENT + return self.parse_lines(lines, goal, builder, flags) + + + def parse_lines(self, lines, goal, builder, flags=0): + # XXX (adim): this is trunk's keyword management + # builder.keywords = self.keywords.copy() + # if flags & CO_FUTURE_WITH_STATEMENT: + # builder.enable_with() + goalnumber = self.symbols[goal] + target = self.root_rules[goalnumber] + src = Source(self, lines, flags) + + if not target.match(src, builder): + line, lineno = src.debug() + # XXX needs better error messages + raise SyntaxError("invalid syntax", lineno, -1, line) + # return None + return builder + + +## def eval(self, source, builder=None): +## if builder is None: +## builder = self.builder +## rule = self.root_rules['eval_input'] +## rule.match(source, builder) + + +def get_pyparser_for_version(version): + parser = PythonParser(predefined_symbols=symbol.sym_name) + return build_parser_for_version(version, parser=parser) + + +# unfortunately the command line options are not parsed yet +debug_print( "Loading grammar %s" % Options.version ) +# PYTHON_PARSER = get_pyparser_for_version(Options.version) +PYTHON_PARSER = get_pyparser_for_version( Options.version ) + + +## XXX BROKEN +## def grammar_rules( space ): +## w_rules = space.newdict() +## for key, value in PYTHON_PARSER.rules.iteritems(): +## space.setitem(w_rules, space.wrap(key), space.wrap(value)) +## return w_rules +## +## +## 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 ) Modified: pypy/branch/ast-experiments/pypy/interpreter/pyparser/pythonutil.py ============================================================================== --- pypy/branch/ast-experiments/pypy/interpreter/pyparser/pythonutil.py (original) +++ pypy/branch/ast-experiments/pypy/interpreter/pyparser/pythonutil.py Thu Dec 14 17:28:05 2006 @@ -1,17 +1,90 @@ -__all__ = ["python_parse", "pypy_parse"] +"""miscelanneous utility functions +XXX: svn mv pythonutil.py gramtools.py / parsertools.py +""" + +import sys +import os import parser -import pythonparse -from tuplebuilder import TupleBuilder -from astbuilder import AstBuilder - -PYTHON_PARSER = pythonparse.PYTHON_PARSER -TARGET_DICT = { - 'exec' : "file_input", - 'eval' : "eval_input", - 'single' : "single_input", - } +from pypy.interpreter.pyparser.grammar import Parser +from pypy.interpreter.pyparser.pytoken import setup_tokens +from pypy.interpreter.pyparser.ebnfgrammar import GRAMMAR_GRAMMAR +from pypy.interpreter.pyparser.ebnflexer import GrammarSource +from pypy.interpreter.pyparser.ebnfparse import EBNFBuilder + +from pypy.interpreter.pyparser.tuplebuilder import TupleBuilder + +PYTHON_VERSION = ".".join([str(i) for i in sys.version_info[:2]]) + +def get_grammar_file(version): + """returns the python grammar corresponding to our CPython version""" + if version == "native": + _ver = PYTHON_VERSION + elif version == "stable": + _ver = "_stablecompiler" + elif version in ("2.3","2.4","2.5a"): + _ver = version + return os.path.join( os.path.dirname(__file__), "data", "Grammar" + _ver ), _ver + + +def build_parser(gramfile, parser=None): + """reads a (EBNF) grammar definition and builds a parser for it""" + if parser is None: + parser = Parser() + setup_tokens(parser) + # XXX: clean up object dependencies + source = GrammarSource(GRAMMAR_GRAMMAR, file(gramfile).read()) + builder = EBNFBuilder(GRAMMAR_GRAMMAR, dest_parser=parser) + GRAMMAR_GRAMMAR.root_rules['grammar'].match(source, builder) + builder.resolve_rules() + parser.build_first_sets() + return parser + + +def build_parser_for_version(version, parser=None): + gramfile, _ = get_grammar_file(version) + return build_parser(gramfile, parser) + + +## XXX: the below code should probably go elsewhere + +## convenience functions for computing AST objects using recparser +def ast_from_input(input, mode, transformer, parser): + """converts a source input into an AST + + - input : the source to be converted + - mode : 'exec', 'eval' or 'single' + - transformer : the transfomer instance to use to convert + the nested tuples into the AST + XXX: transformer could be instantiated here but we don't want + here to explicitly import compiler or stablecompiler or + etc. This is to be fixed in a clean way + """ + builder = TupleBuilder(parser, lineno=True) + parser.parse_source(input, mode, builder) + tuples = builder.stack[-1].as_tuple(True) + return transformer.compile_node(tuples) + + +def pypy_parse(source, mode='exec', lineno=False): + from pypy.interpreter.pyparser.pythonparse import PythonParser, get_pyparser_for_version + from pypy.interpreter.pyparser.astbuilder import AstBuilder + # parser = build_parser_for_version("2.4", PythonParser()) + parser = get_pyparser_for_version('2.4') + builder = TupleBuilder(parser) + parser.parse_source(source, mode, builder) + return builder.stack[-1].as_tuple(lineno) + + +def source2ast(source, mode='exec', version='2.4', space=None): + from pypy.interpreter.pyparser.pythonparse import PythonParser, get_pyparser_for_version + from pypy.interpreter.pyparser.astbuilder import AstBuilder + parser = get_pyparser_for_version(version) + builder = AstBuilder(parser, space=space) + parser.parse_source(source, mode, builder) + return builder + ## convenience functions around CPython's parser functions def python_parsefile(filename, lineno=False): @@ -32,7 +105,6 @@ tp = parser.suite(source) return parser.ast2tuple(tp, line_info=lineno) -## convenience functions around recparser functions def pypy_parsefile(filename, lineno=False): """parse using PyPy's parser module and return a tuple of three elements : @@ -48,105 +120,3 @@ source = pyf.read() pyf.close() return pypy_parse(source, 'exec', lineno) - -def internal_pypy_parse(source, mode='exec', lineno=False, flags=0, space=None, - parser = PYTHON_PARSER): - """This function has no other role than testing the parser's annotation - - annotateme() is basically the same code that pypy_parse(), but with the - following differences : - - - returns a tuplebuilder.StackElement instead of the *real* nested - tuples (StackElement is only a wrapper class around these tuples) - - """ - builder = TupleBuilder(parser, lineno=False) - if space is not None: - builder.space = space - target_rule = TARGET_DICT[mode] - parser.parse_source(source, target_rule, builder, flags) - stack_element = builder.stack[-1] - return (builder.source_encoding, stack_element) - -def parse_result_to_nested_tuples(parse_result, lineno=False): - """NOT_RPYTHON""" - source_encoding, stack_element = parse_result - return stack_element.as_tuple(lineno) - -def pypy_parse(source, mode='exec', lineno=False, flags=0, parser = PYTHON_PARSER): - """ - NOT_RPYTHON ! - parse using PyPy's parser module and return - a tuple of three elements : - - The encoding declaration symbol or None if there were no encoding - statement - - The TupleBuilder's stack top element (instance of - tuplebuilder.StackElement which is a wrapper of some nested tuples - like those returned by the CPython's parser) - - The encoding string or None if there were no encoding statement - nested tuples - """ - source_encoding, stack_element = internal_pypy_parse(source, mode, lineno=lineno, - flags=lineno, parser = parser) - # convert the stack element into nested tuples (caution, the annotator - # can't follow this call) - return parse_result_to_nested_tuples((source_encoding, stack_element), lineno=lineno) - -## convenience functions for computing AST objects using recparser -def ast_from_input(input, mode, transformer, parser = PYTHON_PARSER): - """converts a source input into an AST - - - input : the source to be converted - - mode : 'exec', 'eval' or 'single' - - transformer : the transfomer instance to use to convert - the nested tuples into the AST - XXX: transformer could be instantiated here but we don't want - here to explicitly import compiler or stablecompiler or - etc. This is to be fixed in a clean way - """ - tuples = pypy_parse(input, mode, True, parser) - if 'import' in input: - toto # XXX ? What's the point here ? - return transformer.compile_node(tuples) - -def target_ast_compile(space, input, mode): - from pypy.interpreter.astcompiler import ast, misc, pycodegen - builder = AstBuilder(rules=None, debug=0, space=space) - target = TARGET_DICT[mode] - PYTHON_PARSER.parse_source(input, target, builder) - ast_tree = builder.rule_stack[-1] - misc.set_filename("", ast_tree) - if mode=="single": - codegenerator = pycodegen.InteractiveCodeGenerator(space,ast_tree) - elif mode=="eval": - codegenerator = pycodegen.ExpressionCodeGenerator(space,ast_tree) - elif mode=="exec": - codegenerator = pycodegen.ModuleCodeGenerator(space,ast_tree) - else: - raise ValueError("incorrect mode") - code1 = codegenerator.getCode() - return code1 - - -def internal_pypy_parse_to_ast(source, mode='exec', lineno=False, flags=0): - builder = AstBuilder() - target_rule = TARGET_DICT[mode] - PYTHON_PARSER.parse_source(source, target_rule, builder, flags) - ast_tree = builder.rule_stack[-1] - return (builder.source_encoding, ast_tree) - - -if __name__ == "__main__": - import sys - if len(sys.argv) < 2: - print "python parse.py [-d N] test_file.py" - sys.exit(1) - if sys.argv[1] == "-d": - debug_level = int(sys.argv[2]) - test_file = sys.argv[3] - else: - test_file = sys.argv[1] - print "-"*20 - print - print "pyparse \n", pypy_parsefile(test_file) - print "parser \n", python_parsefile(test_file) Added: pypy/branch/ast-experiments/pypy/interpreter/pyparser/test/expressions.py ============================================================================== --- (empty file) +++ pypy/branch/ast-experiments/pypy/interpreter/pyparser/test/expressions.py Thu Dec 14 17:28:05 2006 @@ -0,0 +1,504 @@ +""" +list of tested expressions / suites (used by test_parser and test_astbuilder) +""" + +constants = [ + "0", + "7", + "-3", + "053", + "0x18", + "14L", + "1.0", + "3.9", + "-3.6", + "1.8e19", + "90000000000000", + "90000000000000.", + "3j" + ] + +expressions = [ + "x = a + 1", + "x = 1 - a", + "x = a * b", + "x = a ** 2", + "x = a / b", + "x = a & b", + "x = a | b", + "x = a ^ b", + "x = a // b", + "x = a * b + 1", + "x = a + 1 * b", + "x = a * b / c", + "x = a * (1 + c)", + "x, y, z = 1, 2, 3", + "x = 'a' 'b' 'c'", + "del foo", + "del foo[bar]", + "del foo.bar", + "l[0]", + "k[v,]", + "m[a,b]", + "a.b.c[d]", + "file('some.txt').read()", + "a[0].read()", + "a[1:1].read()", + "f('foo')('bar')('spam')", + "f('foo')('bar')('spam').read()[0]", + "a.b[0][0]", + "a.b[0][:]", + "a.b[0][::]", + "a.b[0][0].pop()[0].push('bar')('baz').spam", + "a.b[0].read()[1][2].foo().spam()[0].bar", + "a**2", + "a**2**2", + "a.b[0]**2", + "a.b[0].read()[1][2].foo().spam()[0].bar ** 2", + "l[start:end] = l2", + "l[::] = l2", + "a = `s`", + "a = `1 + 2 + f(3, 4)`", + "[a, b] = c", + "(a, b) = c", + "[a, (b,c), d] = e", + "a, (b, c), d = e", + ] + +# We do not export the following tests because we would have to implement 2.5 +# features in the stable compiler (other than just building the AST). +expressions_inbetweenversions = expressions + [ + "1 if True else 2", + "1 if False else 2", + ] + +funccalls = [ + "l = func()", + "l = func(10)", + "l = func(10, 12, a, b=c, *args)", + "l = func(10, 12, a, b=c, **kwargs)", + "l = func(10, 12, a, b=c, *args, **kwargs)", + "l = func(10, 12, a, b=c)", + "e = l.pop(3)", + "e = k.l.pop(3)", + "simplefilter('ignore', category=PendingDeprecationWarning, append=1)", + """methodmap = dict(subdirs=phase4, + same_files=phase3, diff_files=phase3, funny_files=phase3, + common_dirs = phase2, common_files=phase2, common_funny=phase2, + common=phase1, left_only=phase1, right_only=phase1, + left_list=phase0, right_list=phase0)""", + "odata = b2a_qp(data, quotetabs = quotetabs, header = header)", + ] + +listmakers = [ + "l = []", + "l = [1, 2, 3]", + "l = [i for i in range(10)]", + "l = [i for i in range(10) if i%2 == 0]", + "l = [i for i in range(10) if i%2 == 0 or i%2 == 1]", # <-- + "l = [i for i in range(10) if i%2 == 0 and i%2 == 1]", + "l = [i for j in range(10) for i in range(j)]", + "l = [i for j in range(10) for i in range(j) if j%2 == 0]", + "l = [i for j in range(10) for i in range(j) if j%2 == 0 and i%2 == 0]", + "l = [(a, b) for (a,b,c) in l2]", + "l = [{a:b} for (a,b,c) in l2]", + "l = [i for j in k if j%2 == 0 if j*2 < 20 for i in j if i%2==0]", + ] + +genexps = [ + "l = (i for i in j)", + "l = (i for i in j if i%2 == 0)", + "l = (i for j in k for i in j)", + "l = (i for j in k for i in j if j%2==0)", + "l = (i for j in k if j%2 == 0 if j*2 < 20 for i in j if i%2==0)", + "l = (i for i in [ j*2 for j in range(10) ] )", + "l = [i for i in ( j*2 for j in range(10) ) ]", + "l = (i for i in [ j*2 for j in ( k*3 for k in range(10) ) ] )", + "l = [i for j in ( j*2 for j in [ k*3 for k in range(10) ] ) ]", + "l = f(i for i in j)", + ] + + +dictmakers = [ + "l = {a : b, 'c' : 0}", + "l = {}", + ] + +backtrackings = [ + "f = lambda x: x+1", + "f = lambda x,y: x+y", + "f = lambda x,y=1,z=t: x+y", + "f = lambda x,y=1,z=t,*args,**kwargs: x+y", + "f = lambda x,y=1,z=t,*args: x+y", + "f = lambda x,y=1,z=t,**kwargs: x+y", + "f = lambda: 1", + "f = lambda *args: 1", + "f = lambda **kwargs: 1", + ] + +comparisons = [ + "a < b", + "a > b", + "a not in b", + "a is not b", + "a in b", + "a is b", + "3 < x < 5", + "(3 < x) < 5", + "a < b < c < d", + "(a < b) < (c < d)", + "a < (b < c) < d", + ] + +multiexpr = [ + 'a = b; c = d;', + 'a = b = c = d', + ] + +attraccess = [ + 'a.b = 2', + 'x = a.b', + ] + +slices = [ + "l[:]", + "l[::]", + "l[1:2]", + "l[1:]", + "l[:2]", + "l[1::]", + "l[:1:]", + "l[::1]", + "l[1:2:]", + "l[:1:2]", + "l[1::2]", + "l[0:1:2]", + "a.b.l[:]", + "a.b.l[1:2]", + "a.b.l[1:]", + "a.b.l[:2]", + "a.b.l[0:1:2]", + "a[1:2:3, 100]", + "a[:2:3, 100]", + "a[1::3, 100,]", + "a[1:2:, 100]", + "a[1:2, 100]", + "a[1:, 100,]", + "a[:2, 100]", + "a[:, 100]", + "a[100, 1:2:3,]", + "a[100, :2:3]", + "a[100, 1::3]", + "a[100, 1:2:,]", + "a[100, 1:2]", + "a[100, 1:]", + "a[100, :2,]", + "a[100, :]", + ] + +imports = [ + 'import os', + 'import sys, os', + 'import os.path', + 'import os.path, sys', + 'import sys, os.path as osp', + 'import os.path as osp', + 'import os.path as osp, sys as _sys', + 'import a.b.c.d', + 'import a.b.c.d as abcd', + 'from os import path', + 'from os import path, system', + ] + +imports_newstyle = [ + 'from os import path, system', + 'from os import path as P, system as S', + 'from os import (path as P, system as S,)', + 'from os import *', + ] + +if_stmts = [ + "if a == 1: a+= 2", + """if a == 1: + a += 2 +elif a == 2: + a += 3 +else: + a += 4 +""", + "if a and not b == c: pass", + "if a and not not not b == c: pass", + "if 0: print 'foo'" + ] + +asserts = [ + 'assert False', + 'assert a == 1', + 'assert a == 1 and b == 2', + 'assert a == 1 and b == 2, "assertion failed"', + ] + +execs = [ + 'exec a', + 'exec "a=b+3"', + 'exec a in f()', + 'exec a in f(), g()', + ] + +prints = [ + 'print', + 'print a', + 'print a,', + 'print a, b', + 'print a, "b", c', + 'print >> err', + 'print >> err, "error"', + 'print >> err, "error",', + 'print >> err, "error", a', + ] + +globs = [ + 'global a', + 'global a,b,c', + ] + +raises_ = [ # NB. 'raises' creates a name conflict with py.test magic + 'raise', + 'raise ValueError', + 'raise ValueError("error")', + 'raise ValueError, "error"', + 'raise ValueError, "error", foo', + ] + +tryexcepts = [ + """try: + a + b +except: + pass +""", + """try: + a + b +except NameError: + pass +""", + """try: + a + b +except NameError, err: + pass +""", + """try: + a + b +except (NameError, ValueError): + pass +""", + """try: + a + b +except (NameError, ValueError), err: + pass +""", + """try: + a +except NameError, err: + pass +except ValueError, err: + pass +""", + """def f(): + try: + a + except NameError, err: + a = 1 + b = 2 + except ValueError, err: + a = 2 + return a +""" + """try: + a +except NameError, err: + a = 1 +except ValueError, err: + a = 2 +else: + a += 3 +""", + """try: + a +finally: + b +""", + """def f(): + try: + return a + finally: + a = 3 + return 1 +""", + + ] + +one_stmt_funcdefs = [ + "def f(): return 1", + "def f(x): return x+1", + "def f(x,y): return x+y", + "def f(x,y=1,z=t): return x+y", + "def f(x,y=1,z=t,*args,**kwargs): return x+y", + "def f(x,y=1,z=t,*args): return x+y", + "def f(x,y=1,z=t,**kwargs): return x+y", + "def f(*args): return 1", + "def f(**kwargs): return 1", + "def f(t=()): pass", + "def f(a, b, (c, d), e): pass", + "def f(a, b, (c, (d, e), f, (g, h))): pass", + "def f(a, b, (c, (d, e), f, (g, h)), i): pass", + "def f((a)): pass", + ] + +one_stmt_classdefs = [ + "class Pdb(bdb.Bdb, cmd.Cmd): pass", + ] + +docstrings = [ + '''def foo(): return 1''', + '''class Foo: pass''', + '''class Foo: "foo"''', + '''def foo(): + """foo docstring""" + return 1 +''', + '''def foo(): + """foo docstring""" + a = 1 + """bar""" + return a +''', + '''def foo(): + """doc"""; print 1 + a=1 +''', + '''"""Docstring""";print 1''', + ] + +returns = [ + 'def f(): return', + 'def f(): return 1', + 'def f(): return a.b', + 'def f(): return a', + 'def f(): return a,b,c,d', + #'return (a,b,c,d)', --- this one makes no sense, as far as I can tell + ] + +augassigns = [ + 'a=1;a+=2', + 'a=1;a-=2', + 'a=1;a*=2', + 'a=1;a/=2', + 'a=1;a//=2', + 'a=1;a%=2', + 'a=1;a**=2', + 'a=1;a>>=2', + 'a=1;a<<=2', + 'a=1;a&=2', + 'a=1;a^=2', + 'a=1;a|=2', + + 'a=A();a.x+=2', + 'a=A();a.x-=2', + 'a=A();a.x*=2', + 'a=A();a.x/=2', + 'a=A();a.x//=2', + 'a=A();a.x%=2', + 'a=A();a.x**=2', + 'a=A();a.x>>=2', + 'a=A();a.x<<=2', + 'a=A();a.x&=2', + 'a=A();a.x^=2', + 'a=A();a.x|=2', + + 'a=A();a[0]+=2', + 'a=A();a[0]-=2', + 'a=A();a[0]*=2', + 'a=A();a[0]/=2', + 'a=A();a[0]//=2', + 'a=A();a[0]%=2', + 'a=A();a[0]**=2', + 'a=A();a[0]>>=2', + 'a=A();a[0]<<=2', + 'a=A();a[0]&=2', + 'a=A();a[0]^=2', + 'a=A();a[0]|=2', + + 'a=A();a[0:2]+=2', + 'a=A();a[0:2]-=2', + 'a=A();a[0:2]*=2', + 'a=A();a[0:2]/=2', + 'a=A();a[0:2]//=2', + 'a=A();a[0:2]%=2', + 'a=A();a[0:2]**=2', + 'a=A();a[0:2]>>=2', + 'a=A();a[0:2]<<=2', + 'a=A();a[0:2]&=2', + 'a=A();a[0:2]^=2', + 'a=A();a[0:2]|=2', + ] + +PY23_TESTS = [ + constants, + expressions, + augassigns, + comparisons, + funccalls, + backtrackings, + listmakers, # ERRORS + dictmakers, + multiexpr, + attraccess, + slices, + imports, + execs, + prints, + globs, + raises_, + + ] + +OPTIONAL_TESTS = [ + # expressions_inbetweenversions, + genexps, + imports_newstyle, + asserts, + ] + +TESTS = PY23_TESTS + OPTIONAL_TESTS + + +## TESTS = [ +## ["l = [i for i in range(10) if i%2 == 0 or i%2 == 1]"], +## ] + +EXEC_INPUTS = [ + one_stmt_classdefs, + one_stmt_funcdefs, + if_stmts, + tryexcepts, + docstrings, + returns, + ] + +SINGLE_INPUTS = [ + one_stmt_funcdefs, + ['\t # hello\n', + 'print 6*7', + 'if 1: x\n', + 'x = 5', + 'x = 5 ', + '''"""Docstring""";print 1''', + '''"Docstring"''', + '''"Docstring" "\\x00"''', + ] +] Modified: pypy/branch/ast-experiments/pypy/interpreter/pyparser/test/test_astbuilder.py ============================================================================== --- pypy/branch/ast-experiments/pypy/interpreter/pyparser/test/test_astbuilder.py (original) +++ pypy/branch/ast-experiments/pypy/interpreter/pyparser/test/test_astbuilder.py Thu Dec 14 17:28:05 2006 @@ -1,8 +1,9 @@ import os +from pypy.tool.option import Options from pypy.interpreter.pyparser import pythonparse from pypy.interpreter.pyparser.astbuilder import AstBuilder -from pypy.interpreter.pyparser.pythonutil import ast_from_input +from pypy.interpreter.pyparser.pythonutil import ast_from_input, build_parser_for_version from pypy.interpreter.stablecompiler.transformer import Transformer import pypy.interpreter.stablecompiler.ast as test_ast import pypy.interpreter.astcompiler.ast as ast_ast @@ -13,6 +14,9 @@ from pypy.interpreter.astcompiler import ast + +from expressions import TESTS, SINGLE_INPUTS, EXEC_INPUTS + def arglist_equal(left,right): """needs special case because we handle the argumentlist differently""" for l,r in zip(left,right): @@ -142,211 +146,13 @@ return False return True -EXPECTED = {} - -constants = [ - "0", - "7", - "-3", - "053", - "0x18", - "14L", - "1.0", - "3.9", - "-3.6", - "1.8e19", - "90000000000000", - "90000000000000.", - "3j" - ] - -expressions = [ - "x = a + 1", - "x = 1 - a", - "x = a * b", - "x = a ** 2", - "x = a / b", - "x = a & b", - "x = a | b", - "x = a ^ b", - "x = a // b", - "x = a * b + 1", - "x = a + 1 * b", - "x = a * b / c", - "x = a * (1 + c)", - "x, y, z = 1, 2, 3", - "x = 'a' 'b' 'c'", - "del foo", - "del foo[bar]", - "del foo.bar", - "l[0]", - "k[v,]", - "m[a,b]", - "a.b.c[d]", - "file('some.txt').read()", - "a[0].read()", - "a[1:1].read()", - "f('foo')('bar')('spam')", - "f('foo')('bar')('spam').read()[0]", - "a.b[0][0]", - "a.b[0][:]", - "a.b[0][::]", - "a.b[0][0].pop()[0].push('bar')('baz').spam", - "a.b[0].read()[1][2].foo().spam()[0].bar", - "a**2", - "a**2**2", - "a.b[0]**2", - "a.b[0].read()[1][2].foo().spam()[0].bar ** 2", - "l[start:end] = l2", - "l[::] = l2", - "a = `s`", - "a = `1 + 2 + f(3, 4)`", - "[a, b] = c", - "(a, b) = c", - "[a, (b,c), d] = e", - "a, (b, c), d = e", - ] - -# We do not export the following tests because we would have to implement 2.5 -# features in the stable compiler (other than just building the AST). -expressions_inbetweenversions = expressions + [ - "1 if True else 2", - "1 if False else 2", - ] - -EXPECTED["k[v,]"] = ("Module(None, Stmt([Discard(Subscript(Name('k'), 2, " - "Tuple([Name('v')])))]))") -EXPECTED["m[a,b]"] = ("Module(None, Stmt([Discard(Subscript(Name('m'), 2, " - "Tuple([Name('a'), Name('b')])))]))") -EXPECTED["1 if True else 2"] = ("Module(None, Stmt([Discard(CondExpr(" - "Name('True'), Const(1), Const(2)))]))") -EXPECTED["1 if False else 2"] = ("Module(None, Stmt([Discard(CondExpr(" - "Name('False'), Const(1), Const(2)))]))") - -funccalls = [ - "l = func()", - "l = func(10)", - "l = func(10, 12, a, b=c, *args)", - "l = func(10, 12, a, b=c, **kwargs)", - "l = func(10, 12, a, b=c, *args, **kwargs)", - "l = func(10, 12, a, b=c)", - "e = l.pop(3)", - "e = k.l.pop(3)", - "simplefilter('ignore', category=PendingDeprecationWarning, append=1)", - """methodmap = dict(subdirs=phase4, - same_files=phase3, diff_files=phase3, funny_files=phase3, - common_dirs = phase2, common_files=phase2, common_funny=phase2, - common=phase1, left_only=phase1, right_only=phase1, - left_list=phase0, right_list=phase0)""", - "odata = b2a_qp(data, quotetabs = quotetabs, header = header)", - ] - -listmakers = [ - "l = []", - "l = [1, 2, 3]", - "l = [i for i in range(10)]", - "l = [i for i in range(10) if i%2 == 0]", - "l = [i for i in range(10) if i%2 == 0 or i%2 == 1]", - "l = [i for i in range(10) if i%2 == 0 and i%2 == 1]", - "l = [i for j in range(10) for i in range(j)]", - "l = [i for j in range(10) for i in range(j) if j%2 == 0]", - "l = [i for j in range(10) for i in range(j) if j%2 == 0 and i%2 == 0]", - "l = [(a, b) for (a,b,c) in l2]", - "l = [{a:b} for (a,b,c) in l2]", - "l = [i for j in k if j%2 == 0 if j*2 < 20 for i in j if i%2==0]", - ] - -genexps = [ - "l = (i for i in j)", - "l = (i for i in j if i%2 == 0)", - "l = (i for j in k for i in j)", - "l = (i for j in k for i in j if j%2==0)", - "l = (i for j in k if j%2 == 0 if j*2 < 20 for i in j if i%2==0)", - "l = (i for i in [ j*2 for j in range(10) ] )", - "l = [i for i in ( j*2 for j in range(10) ) ]", - "l = (i for i in [ j*2 for j in ( k*3 for k in range(10) ) ] )", - "l = [i for j in ( j*2 for j in [ k*3 for k in range(10) ] ) ]", - "l = f(i for i in j)", - ] +EXPECTED = { + "k[v,]" : "Module(None, Stmt([Discard(Subscript(Name('k'), 2, Tuple([Name('v')])))]))", + "m[a,b]" : "Module(None, Stmt([Discard(Subscript(Name('m'), 2, Tuple([Name('a'), Name('b')])))]))", + "1 if True else 2" : "Module(None, Stmt([Discard(CondExpr(Name('True'), Const(1), Const(2)))]))", + "1 if False else 2" : "Module(None, Stmt([Discard(CondExpr(Name('False'), Const(1), Const(2)))]))", -dictmakers = [ - "l = {a : b, 'c' : 0}", - "l = {}", - ] - -backtrackings = [ - "f = lambda x: x+1", - "f = lambda x,y: x+y", - "f = lambda x,y=1,z=t: x+y", - "f = lambda x,y=1,z=t,*args,**kwargs: x+y", - "f = lambda x,y=1,z=t,*args: x+y", - "f = lambda x,y=1,z=t,**kwargs: x+y", - "f = lambda: 1", - "f = lambda *args: 1", - "f = lambda **kwargs: 1", - ] - -comparisons = [ - "a < b", - "a > b", - "a not in b", - "a is not b", - "a in b", - "a is b", - "3 < x < 5", - "(3 < x) < 5", - "a < b < c < d", - "(a < b) < (c < d)", - "a < (b < c) < d", - ] - -multiexpr = [ - 'a = b; c = d;', - 'a = b = c = d', - ] - -attraccess = [ - 'a.b = 2', - 'x = a.b', - ] - -slices = [ - "l[:]", - "l[::]", - "l[1:2]", - "l[1:]", - "l[:2]", - "l[1::]", - "l[:1:]", - "l[::1]", - "l[1:2:]", - "l[:1:2]", - "l[1::2]", - "l[0:1:2]", - "a.b.l[:]", - "a.b.l[1:2]", - "a.b.l[1:]", - "a.b.l[:2]", - "a.b.l[0:1:2]", - "a[1:2:3, 100]", - "a[:2:3, 100]", - "a[1::3, 100,]", - "a[1:2:, 100]", - "a[1:2, 100]", - "a[1:, 100,]", - "a[:2, 100]", - "a[:, 100]", - "a[100, 1:2:3,]", - "a[100, :2:3]", - "a[100, 1::3]", - "a[100, 1:2:,]", - "a[100, 1:2]", - "a[100, 1:]", - "a[100, :2,]", - "a[100, :]", - ] -EXPECTED.update({ "a[1:2:3, 100]": "Module(None, Stmt([Discard(Subscript(Name('a'), 2, Tuple([Sliceobj([Const(1), Const(2), Const(3)]), Const(100)])))]))", "a[:2:3, 100]": "Module(None, Stmt([Discard(Subscript(Name('a'), 2, Tuple([Sliceobj([Const(None), Const(2), Const(3)]), Const(100)])))]))", "a[1::3, 100,]": "Module(None, Stmt([Discard(Subscript(Name('a'), 2, Tuple([Sliceobj([Const(1), Const(None), Const(3)]), Const(100)])))]))", @@ -363,307 +169,6 @@ "a[100, 1:]": "Module(None, Stmt([Discard(Subscript(Name('a'), 2, Tuple([Const(100), Sliceobj([Const(1), Const(None)])])))]))", "a[100, :2,]": "Module(None, Stmt([Discard(Subscript(Name('a'), 2, Tuple([Const(100), Sliceobj([Const(None), Const(2)])])))]))", "a[100, :]": "Module(None, Stmt([Discard(Subscript(Name('a'), 2, Tuple([Const(100), Sliceobj([Const(None), Const(None)])])))]))", - }) - -imports = [ - 'import os', - 'import sys, os', - 'import os.path', - 'import os.path, sys', - 'import sys, os.path as osp', - 'import os.path as osp', - 'import os.path as osp, sys as _sys', - 'import a.b.c.d', - 'import a.b.c.d as abcd', - 'from os import path', - 'from os import path, system', - ] - -imports_newstyle = [ - 'from os import path, system', - 'from os import path as P, system as S', - 'from os import (path as P, system as S,)', - 'from os import *', - ] - -if_stmts = [ - "if a == 1: a+= 2", - """if a == 1: - a += 2 -elif a == 2: - a += 3 -else: - a += 4 -""", - "if a and not b == c: pass", - "if a and not not not b == c: pass", - "if 0: print 'foo'" - ] - -asserts = [ - 'assert False', - 'assert a == 1', - 'assert a == 1 and b == 2', - 'assert a == 1 and b == 2, "assertion failed"', - ] - -execs = [ - 'exec a', - 'exec "a=b+3"', - 'exec a in f()', - 'exec a in f(), g()', - ] - -prints = [ - 'print', - 'print a', - 'print a,', - 'print a, b', - 'print a, "b", c', - 'print >> err', - 'print >> err, "error"', - 'print >> err, "error",', - 'print >> err, "error", a', - ] - -globs = [ - 'global a', - 'global a,b,c', - ] - -raises_ = [ # NB. 'raises' creates a name conflict with py.test magic - 'raise', - 'raise ValueError', - 'raise ValueError("error")', - 'raise ValueError, "error"', - 'raise ValueError, "error", foo', - ] - -tryexcepts = [ - """try: - a - b -except: - pass -""", - """try: - a - b -except NameError: - pass -""", - """try: - a - b -except NameError, err: - pass -""", - """try: - a - b -except (NameError, ValueError): - pass -""", - """try: - a - b -except (NameError, ValueError), err: - pass -""", - """try: - a -except NameError, err: - pass -except ValueError, err: - pass -""", - """def f(): - try: - a - except NameError, err: - a = 1 - b = 2 - except ValueError, err: - a = 2 - return a -""" - """try: - a -except NameError, err: - a = 1 -except ValueError, err: - a = 2 -else: - a += 3 -""", - """try: - a -finally: - b -""", - """def f(): - try: - return a - finally: - a = 3 - return 1 -""", - - ] - -one_stmt_funcdefs = [ - "def f(): return 1", - "def f(x): return x+1", - "def f(x,y): return x+y", - "def f(x,y=1,z=t): return x+y", - "def f(x,y=1,z=t,*args,**kwargs): return x+y", - "def f(x,y=1,z=t,*args): return x+y", - "def f(x,y=1,z=t,**kwargs): return x+y", - "def f(*args): return 1", - "def f(**kwargs): return 1", - "def f(t=()): pass", - "def f(a, b, (c, d), e): pass", - "def f(a, b, (c, (d, e), f, (g, h))): pass", - "def f(a, b, (c, (d, e), f, (g, h)), i): pass", - "def f((a)): pass", - ] - -one_stmt_classdefs = [ - "class Pdb(bdb.Bdb, cmd.Cmd): pass", - ] - -docstrings = [ - '''def foo(): return 1''', - '''class Foo: pass''', - '''class Foo: "foo"''', - '''def foo(): - """foo docstring""" - return 1 -''', - '''def foo(): - """foo docstring""" - a = 1 - """bar""" - return a -''', - '''def foo(): - """doc"""; print 1 - a=1 -''', - '''"""Docstring""";print 1''', - ] - -returns = [ - 'def f(): return', - 'def f(): return 1', - 'def f(): return a.b', - 'def f(): return a', - 'def f(): return a,b,c,d', - #'return (a,b,c,d)', --- this one makes no sense, as far as I can tell - ] - -augassigns = [ - 'a=1;a+=2', - 'a=1;a-=2', - 'a=1;a*=2', - 'a=1;a/=2', - 'a=1;a//=2', - 'a=1;a%=2', - 'a=1;a**=2', - 'a=1;a>>=2', - 'a=1;a<<=2', - 'a=1;a&=2', - 'a=1;a^=2', - 'a=1;a|=2', - - 'a=A();a.x+=2', - 'a=A();a.x-=2', - 'a=A();a.x*=2', - 'a=A();a.x/=2', - 'a=A();a.x//=2', - 'a=A();a.x%=2', - 'a=A();a.x**=2', - 'a=A();a.x>>=2', - 'a=A();a.x<<=2', - 'a=A();a.x&=2', - 'a=A();a.x^=2', - 'a=A();a.x|=2', - - 'a=A();a[0]+=2', - 'a=A();a[0]-=2', - 'a=A();a[0]*=2', - 'a=A();a[0]/=2', - 'a=A();a[0]//=2', - 'a=A();a[0]%=2', - 'a=A();a[0]**=2', - 'a=A();a[0]>>=2', - 'a=A();a[0]<<=2', - 'a=A();a[0]&=2', - 'a=A();a[0]^=2', - 'a=A();a[0]|=2', - - 'a=A();a[0:2]+=2', - 'a=A();a[0:2]-=2', - 'a=A();a[0:2]*=2', - 'a=A();a[0:2]/=2', - 'a=A();a[0:2]//=2', - 'a=A();a[0:2]%=2', - 'a=A();a[0:2]**=2', - 'a=A();a[0:2]>>=2', - 'a=A();a[0:2]<<=2', - 'a=A();a[0:2]&=2', - 'a=A();a[0:2]^=2', - 'a=A();a[0:2]|=2', - ] - -TESTS = [ - constants, - expressions_inbetweenversions, - augassigns, - comparisons, - funccalls, - backtrackings, - listmakers, - genexps, - dictmakers, - multiexpr, - attraccess, - slices, - imports, - imports_newstyle, - asserts, - execs, - prints, - globs, - raises_, - ] - -EXEC_INPUTS = [ - one_stmt_classdefs, - one_stmt_funcdefs, - if_stmts, - tryexcepts, - docstrings, - returns, - ] - -SINGLE_INPUTS = [ - one_stmt_funcdefs, - ['\t # hello\n', - 'print 6*7', - 'if 1: x\n', - 'x = 5', - 'x = 5 ', - '''"""Docstring""";print 1''', - '''"Docstring"''', - '''"Docstring" "\\x00"''', - ] -] - -TARGET_DICT = { - 'single' : 'single_input', - 'exec' : 'file_input', - 'eval' : 'eval_input', } @@ -704,39 +209,39 @@ builtin = dict(int=int, long=long, float=float, complex=complex) -def ast_parse_expr(expr, target='single'): - target = TARGET_DICT[target] - builder = AstBuilder(space=FakeSpace()) - pythonparse.PYTHON_PARSER.parse_source(expr, target, builder) - return builder - # Create parser from Grammar_stable, not current grammar. -stable_grammar, _ = pythonparse.get_grammar_file("stable") -stable_parser = pythonparse.python_grammar(stable_grammar) +stable_parser = pythonparse.get_pyparser_for_version('stable') +python_parser = pythonparse.get_pyparser_for_version(Options.version) # 'native') # 2.5a') def tuple_parse_expr(expr, target='single'): t = Transformer("dummyfile") return ast_from_input(expr, target, t, stable_parser) -def check_expression(expr, target='single'): - r1 = ast_parse_expr(expr, target) +def source2ast(source, mode, space=FakeSpace()): + builder = AstBuilder(space=space) + python_parser.parse_source(source, mode, builder) + return builder.rule_stack[-1] + +def check_expression(expr, mode='single'): + pypy_ast = source2ast(expr, mode) try: - ast = EXPECTED[expr] + python_ast = EXPECTED[expr] except KeyError: # trust the stablecompiler's Transformer when no explicit result has # been provided (although trusting it is a foolish thing to do) - ast = tuple_parse_expr(expr, target) + python_ast = tuple_parse_expr(expr, mode) check_lineno = True else: - if isinstance(ast, str): - ast = eval(ast, ast_ast.__dict__) + if isinstance(python_ast, str): + python_ast = eval(python_ast, ast_ast.__dict__) check_lineno = False print "-" * 30 - print "ORIG :", ast + print "ORIG :", python_ast print - print "BUILT:", r1.rule_stack[-1] + print "BUILT:", pypy_ast print "-" * 30 - assert nodes_equal(ast, r1.rule_stack[-1], check_lineno), 'failed on %r' % (expr) + assert nodes_equal(python_ast, pypy_ast, check_lineno), 'failed on %r' % (expr) + def test_basic_astgen(): for family in TESTS: @@ -748,6 +253,7 @@ for expr in family: yield check_expression, expr, 'exec' + NEW_GRAMMAR_SNIPPETS = [ 'snippet_with_1.py', 'snippet_with_2.py', @@ -809,7 +315,7 @@ for snippet_name in LIBSTUFF: filepath = os.path.join(os.path.dirname(__file__), '../../../lib', snippet_name) source = file(filepath).read() - yield check_expression, source, 'exec' + yield check_expression, source, 'exec' # FIXME: find the sys' attribute that define this STDLIB_PATH = os.path.dirname(os.__file__) Modified: pypy/branch/ast-experiments/pypy/interpreter/pyparser/test/test_astcompiler.py ============================================================================== --- pypy/branch/ast-experiments/pypy/interpreter/pyparser/test/test_astcompiler.py (original) +++ pypy/branch/ast-experiments/pypy/interpreter/pyparser/test/test_astcompiler.py Thu Dec 14 17:28:05 2006 @@ -1,4 +1,6 @@ +import sys import os + from pypy.interpreter.pyparser import pythonparse from pypy.interpreter.pyparser.astbuilder import AstBuilder from pypy.interpreter.pyparser.tuplebuilder import TupleBuilder @@ -11,92 +13,47 @@ from pypy.interpreter.astcompiler import ast, misc, pycodegen -from test_astbuilder import expressions, comparisons, funccalls, backtrackings,\ - listmakers, genexps, dictmakers, multiexpr, attraccess, slices, imports,\ - asserts, execs, prints, globs, raises_, imports_newstyle, augassigns, \ - if_stmts, one_stmt_classdefs, one_stmt_funcdefs, tryexcepts, docstrings, \ - returns, SNIPPETS, SINGLE_INPUTS, LIBSTUFF, constants - -from test_astbuilder import FakeSpace - - -TESTS = [ - constants, - expressions, - augassigns, - comparisons, - funccalls, - backtrackings, - listmakers, - dictmakers, - multiexpr, - genexps, - attraccess, - slices, - imports, - execs, - prints, - globs, - raises_, -# EXEC_INPUTS - one_stmt_classdefs, - one_stmt_funcdefs, - if_stmts, - tryexcepts, - docstrings, - returns, - ] +from test_astbuilder import SNIPPETS, LIBSTUFF, FakeSpace, source2ast +from expressions import PY23_TESTS, EXEC_INPUTS, SINGLE_INPUTS, OPTIONAL_TESTS + +TESTS = PY23_TESTS + EXEC_INPUTS + -import sys if sys.version_info[0]==2 and sys.version_info[1]>=4: # genexps and new style import don't work on python2.3 # TESTS.append(genexps) XXX: 2.4 optimizes bytecode so our comparison doesn't work - TESTS.append(imports_newstyle) - # assertions give different bytecode with 2.4 (optimize if __debug__) - TESTS.append(asserts) -TARGET_DICT = { - 'single' : 'single_input', - 'exec' : 'file_input', - 'eval' : 'eval_input', - } - -def ast_parse_expr(expr, target='single', space=FakeSpace()): - target = TARGET_DICT[target] - builder = AstBuilder(space=space) - pythonparse.PYTHON_PARSER.parse_source(expr, target, builder) - return builder.rule_stack[-1] + TESTS += OPTIONAL_TESTS -def compile_with_astcompiler(expr, target='exec', space=FakeSpace()): - ast = ast_parse_expr(expr, target='exec', space=space) # xxx exec: single not really tested, mumble +def compile_with_astcompiler(expr, mode='exec', space=FakeSpace()): + ast = source2ast(expr, mode, space) # xxx exec: single not really tested, mumble misc.set_filename('', ast) - if target == 'exec': + if mode == 'exec': Generator = pycodegen.ModuleCodeGenerator - elif target == 'single': + elif mode == 'single': Generator = pycodegen.InteractiveCodeGenerator - elif target == 'eval': + elif mode == 'eval': Generator = pycodegen.ExpressionCodeGenerator codegen = Generator(space, ast) rcode = codegen.getCode() return rcode # Create parser from Grammar_stable, not current grammar. -stable_grammar, _ = pythonparse.get_grammar_file("stable") -stable_parser = pythonparse.python_grammar(stable_grammar) +stable_parser = pythonparse.get_pyparser_for_version('stable') -def compile_with_testcompiler(expr, target='exec', space=FakeSpace()): - target2 = TARGET_DICT['exec'] # xxx exec: single not really tested - builder = TupleBuilder() - stable_parser.parse_source(expr, target2, builder) +def compile_with_testcompiler(expr, mode='exec', space=FakeSpace()): + mode2 = 'exec' # xxx exec: single not really tested + builder = TupleBuilder(stable_parser) + stable_parser.parse_source(expr, mode2, builder) tuples = builder.stack[-1].as_tuple(True) from pypy.interpreter.stablecompiler import transformer, pycodegen, misc ast = transformer.Transformer('').compile_node(tuples) misc.set_filename('', ast) - if target == 'exec': + if mode == 'exec': Generator = pycodegen.ModuleCodeGenerator - elif target == 'single': + elif mode == 'single': Generator = pycodegen.InteractiveCodeGenerator - elif target == 'eval': + elif mode == 'eval': Generator = pycodegen.ExpressionCodeGenerator codegen = Generator(ast) rcode = codegen.getCode() @@ -150,7 +107,7 @@ tuple(rcode.co_cellvars) ) return code -def check_compile(expr, target='exec', quiet=False, space=None): +def check_compile(expr, mode='exec', quiet=False, space=None): if expr == "k[v,]": py.test.skip('bug of the reference "stable compiler"') if not quiet: @@ -159,31 +116,18 @@ if space is None: space = std_space - sc_code = compile_with_testcompiler(expr, target=target) - ac_code = compile_with_astcompiler(expr, target=target, space=space) + sc_code = compile_with_testcompiler(expr, mode=mode) + ac_code = compile_with_astcompiler(expr, mode=mode, space=space) compare_code(ac_code, sc_code, space=space) -## def check_compile( expr ): -## space = FakeSpace() -## ast_tree = ast_parse_expr( expr, target='exec', space=space ) -## misc.set_filename("", ast_tree) -## print "Compiling:", expr -## print ast_tree -## codegenerator = pycodegen.ModuleCodeGenerator(space,ast_tree) -## rcode = codegenerator.getCode() -## code1 = to_code( rcode ) -## code2 = ast_compile( expr ) -## compare_code(code1,code2) def test_compile_argtuple_1(): - #py.test.skip('will be tested when more basic stuff will work') code = """def f( x, (y,z) ): print x,y,z """ check_compile( code ) def test_compile_argtuple_2(): - #py.test.skip('will be tested when more basic stuff will work') code = """def f( x, (y,(z,t)) ): print x,y,z,t """ @@ -191,14 +135,12 @@ def test_compile_argtuple_3(): - #py.test.skip('will be tested when more basic stuff will work') code = """def f( x, (y,(z,(t,u))) ): print x,y,z,t,u """ check_compile( code ) - def test_basic_astgen(): for family in TESTS: for expr in family: Modified: pypy/branch/ast-experiments/pypy/interpreter/pyparser/test/test_samples.py ============================================================================== --- pypy/branch/ast-experiments/pypy/interpreter/pyparser/test/test_samples.py (original) +++ pypy/branch/ast-experiments/pypy/interpreter/pyparser/test/test_samples.py Thu Dec 14 17:28:05 2006 @@ -5,14 +5,15 @@ import py.test + +from pypy.tool.option import Options from pypy.interpreter.pyparser.pythonutil import python_parsefile, \ - pypy_parsefile, python_parse, pypy_parse + pypy_parsefile, pypy_parse, python_parse, get_grammar_file, PYTHON_VERSION from pypy.interpreter.pyparser import grammar from pypy.interpreter.pyparser.pythonlexer import TokenError -from pypy.interpreter.pyparser.pythonparse import PYTHON_VERSION, PYPY_VERSION grammar.DEBUG = False - +_, PYPY_VERSION = get_grammar_file( Options.version ) # these samples are skipped if the native version of Python does not match # the version of the grammar we use GRAMMAR_MISMATCH = PYTHON_VERSION != PYPY_VERSION Modified: pypy/branch/ast-experiments/pypy/interpreter/stablecompiler/transformer.py ============================================================================== --- pypy/branch/ast-experiments/pypy/interpreter/stablecompiler/transformer.py (original) +++ pypy/branch/ast-experiments/pypy/interpreter/stablecompiler/transformer.py Thu Dec 14 17:28:05 2006 @@ -26,9 +26,7 @@ # and replace OWNER, ORGANIZATION, and YEAR as appropriate. # make sure we import the parser with the correct grammar -from pypy.interpreter.pyparser import pythonparse - -import pypy.interpreter.pyparser.pythonparse as pythonparse +from pypy.interpreter.pyparser.pythonparse import get_pyparser_for_version from pypy.interpreter.stablecompiler.ast import * import parser @@ -36,15 +34,16 @@ import sys # Create parser from Grammar_stable, not current grammar. -stable_grammar, _ = pythonparse.get_grammar_file("stable") -stable_parser = pythonparse.python_grammar(stable_grammar) +# stable_grammar, _ = pythonparse.get_grammar_file("stable") +# stable_parser = pythonparse.python_grammar(stable_grammar) -sym_name = stable_parser.symbols.sym_name +stable_parser = get_pyparser_for_version('stable') class symbol: pass - -for value, name in sym_name.iteritems(): +sym_name = {} +for name, value in stable_parser.symbols.items(): + sym_name[value] = name setattr(symbol, name, value) # transforming is requiring a lot of recursion depth so make sure we have enough @@ -58,6 +57,7 @@ from consts import CO_VARARGS, CO_VARKEYWORDS from consts import OP_ASSIGN, OP_DELETE, OP_APPLY + def parseFile(path): f = open(path, "U") # XXX The parser API tolerates files without a trailing newline, @@ -130,6 +130,7 @@ for value, name in sym_name.items(): if hasattr(self, name): self._dispatch[value] = getattr(self, name) + self._dispatch[token.NEWLINE] = self.com_NEWLINE self._atom_dispatch = {token.LPAR: self.atom_lpar, token.LSQB: self.atom_lsqb, @@ -223,7 +224,6 @@ assert isinstance(stmts[0], Discard) assert isinstance(stmts[0].expr, Const) del stmts[0] - return Module(doc, Stmt(stmts)) def eval_input(self, nodelist): @@ -608,6 +608,7 @@ return self.com_generator_expression(test, nodelist[1]) return self.testlist(nodelist) + def test(self, nodelist): # test: or_test ['if' or_test 'else' test] | lambdef if len(nodelist) == 1: @@ -618,8 +619,10 @@ return self.com_node(nodelist[0]) else: # Here we implement conditional expressions - return ast.CondExpr(nodelist[2], nodelist[0], nodelist[4], - nodelist[1].lineno) + # XXX: CPython's nodename is IfExp, not CondExpr + return CondExpr(delist[2], nodelist[0], nodelist[4], + nodelist[1].lineno) + def and_test(self, nodelist): # not_test ('and' not_test)* @@ -632,6 +635,9 @@ assert len(nodelist) == 1 return self.com_node(nodelist[0]) + # XXX + # test = old_test + def or_test(self, nodelist): # or_test: and_test ('or' and_test)* return self.com_binary(Or, nodelist) @@ -920,7 +926,7 @@ # String together the dotted names and return the string name = "" for n in node: - if type(n) == type(()) and n[0] == 1: + if type(n) == type(()) and n[0] == stable_parser.tokens['NAME']: name = name + n[1] + '.' return name[:-1] Modified: pypy/branch/ast-experiments/pypy/module/recparser/pyparser.py ============================================================================== --- pypy/branch/ast-experiments/pypy/module/recparser/pyparser.py (original) +++ pypy/branch/ast-experiments/pypy/module/recparser/pyparser.py Thu Dec 14 17:28:05 2006 @@ -8,7 +8,7 @@ from pypy.interpreter.typedef import interp_attrproperty, GetSetProperty from pypy.interpreter.pycode import PyCode from pypy.interpreter.pyparser.syntaxtree import TokenNode, SyntaxNode, AbstractSyntaxVisitor -from pypy.interpreter.pyparser.pythonutil import PYTHON_PARSER +from pypy.interpreter.pyparser.pythonparse import PYTHON_PARSER from pypy.interpreter.pyparser.error import SyntaxError from pypy.interpreter.pyparser import grammar, symbol, pytoken from pypy.interpreter.argument import Arguments From ac at codespeak.net Thu Dec 14 18:51:37 2006 From: ac at codespeak.net (ac at codespeak.net) Date: Thu, 14 Dec 2006 18:51:37 +0100 (CET) Subject: [pypy-svn] r35758 - pypy/dist/pypy/jit/codegen/i386/test Message-ID: <20061214175137.8BC691007A@code0.codespeak.net> Author: ac Date: Thu Dec 14 18:51:36 2006 New Revision: 35758 Added: pypy/dist/pypy/jit/codegen/i386/test/test_genc_tlc.py (contents, props changed) Modified: pypy/dist/pypy/jit/codegen/i386/test/test_genc_portal.py Log: (pedronis, arre) Add more tests and fix portal tests. Modified: pypy/dist/pypy/jit/codegen/i386/test/test_genc_portal.py ============================================================================== --- pypy/dist/pypy/jit/codegen/i386/test/test_genc_portal.py (original) +++ pypy/dist/pypy/jit/codegen/i386/test/test_genc_portal.py Thu Dec 14 18:51:36 2006 @@ -14,8 +14,10 @@ annhelper = self.hrtyper.annhelper convert_result = getattr(self.main, 'convert_result', str) annotator = self.rtyper.annotator - args_s = [annotator.binding(v) for v in self.maingraph.getargs()] - s_result = self.rtyper.annotator.binding(self.maingraph.getreturnvar()) + args_s = [annmodel.lltype_to_annotation(v.concretetype) + for v in self.maingraph.getargs()] + retvar = self.maingraph.getreturnvar() + s_result = annmodel.lltype_to_annotation(retvar.concretetype) main_fnptr = self.rtyper.type_system.getcallable(self.maingraph) main = PseudoHighLevelCallable(main_fnptr, args_s, s_result) Added: pypy/dist/pypy/jit/codegen/i386/test/test_genc_tlc.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/jit/codegen/i386/test/test_genc_tlc.py Thu Dec 14 18:51:36 2006 @@ -0,0 +1,12 @@ +import py +from pypy.jit.timeshifter.test import test_tlc +from pypy.jit.codegen.i386.test.test_genc_portal import I386PortalTestMixin + + +class TestTLC(I386PortalTestMixin, + test_tlc.TestTLC): + + # for the individual tests see + # ====> ../../../timeshifter/test/test_tl.py + + pass From ac at codespeak.net Thu Dec 14 19:50:19 2006 From: ac at codespeak.net (ac at codespeak.net) Date: Thu, 14 Dec 2006 19:50:19 +0100 (CET) Subject: [pypy-svn] r35759 - in pypy/dist/pypy/jit/codegen/i386: . test Message-ID: <20061214185019.84CB610076@code0.codespeak.net> Author: ac Date: Thu Dec 14 19:50:18 2006 New Revision: 35759 Modified: pypy/dist/pypy/jit/codegen/i386/codebuf.py pypy/dist/pypy/jit/codegen/i386/rgenop.py pypy/dist/pypy/jit/codegen/i386/test/test_genc_portal.py pypy/dist/pypy/jit/codegen/i386/test/test_interp_ts.py Log: (pedronis, arre) Delay creating the codeblock for a builder in order to reduce the number of open codeblocks. This didn't reduce the number very much (on richards from 114 to 112). More work is needed: it seems that the source of open mcs are "open" builders put on queues by collect_split. Modified: pypy/dist/pypy/jit/codegen/i386/codebuf.py ============================================================================== --- pypy/dist/pypy/jit/codegen/i386/codebuf.py (original) +++ pypy/dist/pypy/jit/codegen/i386/codebuf.py Thu Dec 14 19:50:18 2006 @@ -135,7 +135,6 @@ def __init__(self, map_size): self._size = map_size self._pos = 0 - self._data = lltype.malloc(BUF, map_size) self._base = LLTypeMachineCodeBlock.state.base LLTypeMachineCodeBlock.state.base += 2 * map_size @@ -143,13 +142,20 @@ p = self._pos if p + len(data) > self._size: raise CodeBlockOverflow - for c in data: - self._data[p] = c - p += 1 - self._pos = p + self._pos += len(data) + return def tell(self): return self._base + 2 * self._pos def done(self): pass + +class LLTypeInMemoryCodeBuilder(LLTypeMachineCodeBlock): + _last_dump_start = 0 + + def __init__(self, start, end): + self._size = (end - start) / 2 + self._pos = 0 + self._base = start + 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 Thu Dec 14 19:50:18 2006 @@ -1,8 +1,8 @@ -import sys, py +import sys, py, os from pypy.rlib.objectmodel import specialize from pypy.rpython.lltypesystem import lltype, llmemory from pypy.jit.codegen.i386.ri386 import * -from pypy.jit.codegen.i386.codebuf import InMemoryCodeBuilder, CodeBlockOverflow +from pypy.jit.codegen.i386.codebuf import CodeBlockOverflow from pypy.jit.codegen.model import AbstractRGenOp, GenLabel, GenBuilder from pypy.jit.codegen.model import GenVar, GenConst, CodeGenSwitch from pypy.rlib import objectmodel @@ -149,7 +149,9 @@ def __init__(self, rgenop): self.rgenop = rgenop - self.default_case_addr = 0 + self.default_case_builder = None + self.default_case_key = 0 + self._je_key = 0 def initialize(self, builder, gv_exitswitch): mc = builder.mc @@ -171,62 +173,101 @@ newmc = self.rgenop.open_mc() self._reserve(newmc) self.rgenop.close_mc(newmc) - fullmc = InMemoryCodeBuilder(start, end) + fullmc = self.rgenop.InMemoryCodeBuilder(start, end) fullmc.JMP(rel32(self.nextfreepos)) fullmc.done() def add_case(self, gv_case): rgenop = self.rgenop targetbuilder = Builder._new_from_state(rgenop, self.saved_state) - target_addr = targetbuilder.mc.tell() try: - self._add_case(gv_case, target_addr) + self._add_case(gv_case, targetbuilder) except CodeBlockOverflow: self._reserve_more() - self._add_case(gv_case, target_addr) + self._add_case(gv_case, targetbuilder) return targetbuilder - def _add_case(self, gv_case, target_addr): + def _add_case(self, gv_case, targetbuilder): start = self.nextfreepos end = self.endfreepos - mc = InMemoryCodeBuilder(start, end) + mc = self.rgenop.InMemoryCodeBuilder(start, end) mc.CMP(eax, gv_case.operand(None)) - mc.JE(rel32(target_addr)) + self._je_key = targetbuilder.come_from(mc, 'JE', self._je_key) pos = mc.tell() - if self.default_case_addr: - mc.JMP(rel32(self.default_case_addr)) + if self.default_case_builder: + self.default_case_key = self.default_case_builder.come_from( + mc, 'JMP', self.default_case_key) else: illegal_start = mc.tell() mc.JMP(rel32(0)) ud2_addr = mc.tell() mc.UD2() - illegal_mc = InMemoryCodeBuilder(illegal_start, end) + illegal_mc = self.rgenop.InMemoryCodeBuilder(illegal_start, end) illegal_mc.JMP(rel32(ud2_addr)) mc.done() + self._je_key = 0 self.nextfreepos = pos def add_default(self): rgenop = self.rgenop targetbuilder = Builder._new_from_state(rgenop, self.saved_state) - self.default_case_addr = targetbuilder.mc.tell() + self.default_case_builder = targetbuilder start = self.nextfreepos end = self.endfreepos - mc = InMemoryCodeBuilder(start, end) - mc.JMP(rel32(self.default_case_addr)) - mc.done() + mc = self.rgenop.InMemoryCodeBuilder(start, end) + self.default_case_key = targetbuilder.come_from(mc, 'JMP') return targetbuilder class Builder(GenBuilder): - def __init__(self, rgenop, mc, stackdepth): + def __init__(self, rgenop, mc_factory, stackdepth): self.rgenop = rgenop self.stackdepth = stackdepth - self.mc = mc - + self.mc = None + self._mc_factory = mc_factory + self._pending_come_from = {} + self.start = 0 + rgenop.openbuilders += 1 + #os.write(1, 'Open builders+: %d\n' % rgenop.openbuilders) + + def _open(self): + if self.mc is None and self._pending_come_from is not None: + self.mc = self._mc_factory() + self.start = self.mc.tell() + come_froms = self._pending_come_from + self._pending_come_from = None + for start, (end, insn) in come_froms.iteritems(): + mc = self.rgenop.InMemoryCodeBuilder(start, end) + self._emit_come_from(mc, insn, self.start) + mc.done() + + def _emit_come_from(self, mc, insn, addr): + if insn == 'JMP': + mc.JMP(rel32(addr)) + elif insn == 'JE': + mc.JE(rel32(addr)) + elif insn == 'JNE': + mc.JNE(rel32(addr)) + else: + raise ValueError('Unsupported jump') + + def come_from(self, mc, insn, key=0): + start = mc.tell() + if self._pending_come_from is None: + self._emit_come_from(mc, insn, self.start) + else: + self._emit_come_from(mc, insn, 0) + end = mc.tell() + if key != 0: + del self._pending_come_from[key] + self._pending_come_from[start] = (end, insn) + return start + def end(self): pass def _write_prologue(self, sigtoken): + self._open() numargs = sigtoken # for now #self.mc.BREAKPOINT() return [Var(pos) for pos in range(numargs-1, -1, -1)] @@ -235,6 +276,8 @@ self.mc.done() self.rgenop.close_mc(self.mc) self.mc = None + self.rgenop.openbuilders -= 1 + #os.write(1, 'Open builders-: %d\n' % self.rgenop.openbuilders) def _fork(self): return self.rgenop.openbuilder(self.stackdepth) @@ -389,6 +432,7 @@ self.mc.BREAKPOINT() def enter_next_block(self, kinds, args_gv): + self._open() arg_positions = [] seen = {} for i in range(len(args_gv)): @@ -405,13 +449,13 @@ def jump_if_false(self, gv_condition): targetbuilder = self._fork() self.mc.CMP(gv_condition.operand(self), imm8(0)) - self.mc.JE(rel32(targetbuilder.mc.tell())) + targetbuilder.come_from(self.mc, 'JE') return targetbuilder def jump_if_true(self, gv_condition): targetbuilder = self._fork() self.mc.CMP(gv_condition.operand(self), imm8(0)) - self.mc.JNE(rel32(targetbuilder.mc.tell())) + targetbuilder.come_from(self.mc, 'JNE') return targetbuilder def finish_and_return(self, sigtoken, gv_returnvar): @@ -885,12 +929,13 @@ def show_incremental_progress(self): pass - class RI386GenOp(AbstractRGenOp): from pypy.jit.codegen.i386.codebuf import MachineCodeBlock + from pypy.jit.codegen.i386.codebuf import InMemoryCodeBuilder MC_SIZE = 65536 - + openbuilders = 0 + def __init__(self): self.mcs = [] # machine code blocks where no-one is currently writing self.keepalive_gc_refs = [] @@ -903,6 +948,7 @@ else: # XXX supposed infinite for now self.total_code_blocks += 1 + #os.write(1, 'Open codeblocks: %d\n' % (self.total_code_blocks,)) return self.MachineCodeBlock(self.MC_SIZE) def close_mc(self, mc): @@ -915,12 +961,13 @@ assert len(self.mcs) == self.total_code_blocks def openbuilder(self, stackdepth): - return Builder(self, self.open_mc(), stackdepth) + return Builder(self, self.open_mc, stackdepth) def newgraph(self, sigtoken, name): numargs = sigtoken # for now initialstackdepth = numargs+1 builder = self.openbuilder(initialstackdepth) + builder._open() # Force builder to have an mc entrypoint = builder.mc.tell() inputargs_gv = builder._write_prologue(sigtoken) return builder, IntConst(entrypoint), inputargs_gv Modified: pypy/dist/pypy/jit/codegen/i386/test/test_genc_portal.py ============================================================================== --- pypy/dist/pypy/jit/codegen/i386/test/test_genc_portal.py (original) +++ pypy/dist/pypy/jit/codegen/i386/test/test_genc_portal.py Thu Dec 14 19:50:18 2006 @@ -59,6 +59,9 @@ backendoptimize=backendoptimize) cmdargs = ' '.join([str(arg) for arg in main_args]) output = self.cbuilder.cmdexec(cmdargs) + print '-'*60 + print output + print '-'*60 lines = output.split() lastline = lines[-1] assert not lastline.startswith('EXCEPTION:') 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 Dec 14 19:50:18 2006 @@ -13,6 +13,8 @@ class RGenOp(RGenOpPacked): from pypy.jit.codegen.i386.codebuf import LLTypeMachineCodeBlock \ as MachineCodeBlock + from pypy.jit.codegen.i386.codebuf import LLTypeInMemoryCodeBuilder \ + as InMemoryCodeBuilder def timeshift(self, ll_function, values, opt_consts=[], *args, **kwds): values = self.timeshift_cached(ll_function, values, *args, **kwds) From antocuni at codespeak.net Thu Dec 14 21:15:44 2006 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Thu, 14 Dec 2006 21:15:44 +0100 (CET) Subject: [pypy-svn] r35760 - pypy/dist/pypy/translator Message-ID: <20061214201544.C3D0B1007C@code0.codespeak.net> Author: antocuni Date: Thu Dec 14 21:15:42 2006 New Revision: 35760 Modified: pypy/dist/pypy/translator/driver.py Log: Enable merge_if_blocks for the cli backend. Modified: pypy/dist/pypy/translator/driver.py ============================================================================== --- pypy/dist/pypy/translator/driver.py (original) +++ pypy/dist/pypy/translator/driver.py Thu Dec 14 21:15:42 2006 @@ -346,14 +346,17 @@ def task_backendopt_ootype(self): from pypy.translator.backendopt.all import backend_optimizations - backend_optimizations(self.translator, - raisingop2direct_call=False, - inline_threshold=0, - mallocs=False, - merge_if_blocks=False, - constfold=True, - heap2stack=False, - clever_malloc_removal=False) + opt = dict( + raisingop2direct_call=False, + inline_threshold=0, + mallocs=False, + merge_if_blocks=False, + constfold=True, + heap2stack=False, + clever_malloc_removal=False) + if self.config.translation.backend == 'cli': + opt['merge_if_blocks'] = True + backend_optimizations(self.translator, **opt) # task_backendopt_ootype = taskdef(task_backendopt_ootype, [OOTYPE], "ootype back-end optimisations") From guido at codespeak.net Thu Dec 14 23:09:51 2006 From: guido at codespeak.net (guido at codespeak.net) Date: Thu, 14 Dec 2006 23:09:51 +0100 (CET) Subject: [pypy-svn] r35770 - in pypy/dist/pypy/tool/build: . bin test Message-ID: <20061214220951.5F1801007A@code0.codespeak.net> Author: guido Date: Thu Dec 14 23:09:47 2006 New Revision: 35770 Added: pypy/dist/pypy/tool/build/outputbuffer.py pypy/dist/pypy/tool/build/test/test_outputbuffer.py Modified: pypy/dist/pypy/tool/build/bin/client pypy/dist/pypy/tool/build/client.py pypy/dist/pypy/tool/build/config.py Log: Added code to check out from SVN. Also made that compilation is now done in a seperate process (using py.execnet.PopenGateway). Modified: pypy/dist/pypy/tool/build/bin/client ============================================================================== --- pypy/dist/pypy/tool/build/bin/client (original) +++ pypy/dist/pypy/tool/build/bin/client Thu Dec 14 23:09:47 2006 @@ -1,5 +1,6 @@ #!/usr/bin/python +import py import path import sys import random @@ -7,15 +8,80 @@ from pypy.tool.build import config as buildconfig from py.execnet import SshGateway, PopenGateway -from pypy.tool.build.client import init, zip_result, OutputBuffer +from pypy.tool.build.client import init, zip_result from pypy.tool.build import build from pypy.config.config import to_optparse, Config -from pypy.config import pypyoption -from pypy.interpreter.error import OperationError -from pypy.translator.goal import targetpypystandalone -from pypy.translator.driver import TranslationDriver -from pypy.tool.udir import udir +def compile(wc, compileinfo): + code = """\ +import sys + +# interpolating the path +sys.path = [%r] + sys.path + +# nasty, interpolating a large chunk of code (OutputBuffer) +%s + +# interpolating config +compileinfo = %r + +log = open('/tmp/buildclient.log', 'a') +outbuffer = OutputBuffer(log) +sys.stdout = outbuffer +sys.stderr = outbuffer +try: + try: + from pypy.interpreter.error import OperationError + from pypy.translator.goal import targetpypystandalone + from pypy.translator.driver import TranslationDriver + from pypy.config import pypyoption + from pypy.tool.udir import udir + + config = pypyoption.get_pypy_config() + config.override(compileinfo) + + driver = TranslationDriver.from_targetspec( + targetpypystandalone.__dict__, config=config, + default_goal='compile') + driver.proceed(['compile']) + except Exception, e: + # XXX we may want to check + exception_occurred = True + exc, e, tb = sys.exc_info() + print '=' * 79 + print 'Exception during compilation:' + print '%%s: %%s' %% (exc, e) + print + print '\\n'.join(traceback.format_tb(tb)) + print '=' * 79 + del tb + channel.send(None) + else: + channel.send(str(udir)) +finally: + sys.stdout = sys.__stdout__ + sys.stderr = sys.__stderr__ + log.close() +channel.send(outbuffer.getvalue()) +""" + gw = PopenGateway() + buffercode = py.magic.autopath().dirpath().dirpath()\ + .join('outputbuffer.py').read() + interpolated = code % (str(wc), buffercode, compileinfo) + channel = gw.remote_exec(interpolated) + upath = channel.receive() + output = channel.receive() + + return upath, output + +def tempdir(): + i = 0 + tmp = py.path.local('/tmp') + while 1: + dirname = 'buildtemp-%s' % (i,) + if not tmp.join(dirname).check(): + return tmp.ensure(dirname, dir=True) + i += 1 if buildconfig.server in ['localhost', '127.0.0.1']: gw = PopenGateway() @@ -27,12 +93,6 @@ path=buildconfig.path, port=buildconfig.port) -def compile(config): - driver = TranslationDriver.from_targetspec( - targetpypystandalone.__dict__, config=config, - default_goal='compile') - driver.proceed(['compile']) - print channel.receive() # welcome message try: try: @@ -61,7 +121,7 @@ name = '%s.%s' % (checker.im_class.__name__, checker.im_func.func_name) else: - name = checer.func_name + name = checker.func_name print 'request refused by checker', name accepting = False break @@ -71,35 +131,30 @@ continue # XXX we should compile here, using data dict for info print 'compilation requested for %s\nbuilding...\n' % (request,) - config = pypyoption.get_pypy_config() - config.override(request.compileinfo) - buffer = OutputBuffer(sys.__stderr__) - sys.stdout = buffer - sys.stderr = buffer - exception_occurred = False + # subversion checkout + print 'checking out %s@%s' % (request.svnurl, + request.normalized_rev) + #temp = tempdir() + #svnwc = py.path.svnwc(temp) + #svnwc.checkout(request.svnurl) + #svnwc.update(request.normalized_rev) + svnwc = py.path.svnwc('/tmp/buildtemp-1') try: - try: - compile(config) - except Exception, e: - exception_occurred = True - exc, e, tb = sys.exc_info() - print '=' * 79 - print 'Exception during compilation:' - print '%s: %s' % (exc, e) - print - print '\n'.join(traceback.format_tb(tb)) - print '=' * 79 - del tb - finally: - sys.stdout = sys.__stdout__ - sys.stderr = sys.__stderr__ + print 'starting compilation' + upath, log = compile(svnwc, request.compileinfo) + print 'compilation done' + except KeyboardInterrupt: + print 'quitting...' + break - if not exception_occurred: + if upath: # send over zip data, end with a None - zip_result(udir, channel) + print 'compilation successful, sending to server' + zip_result(py.path.local(udir), channel) else: + print 'compilation failed, sending log' # just send the None channel.send(None) Modified: pypy/dist/pypy/tool/build/client.py ============================================================================== --- pypy/dist/pypy/tool/build/client.py (original) +++ pypy/dist/pypy/tool/build/client.py Thu Dec 14 23:09:47 2006 @@ -130,19 +130,3 @@ continue zip.close() -class OutputBuffer(object): - def __init__(self, print_channel=None): - self.print_channel = print_channel - self.buffer = StringIO() - - def write(self, s): - self.buffer.write(s) - if self.print_channel: - self.print_channel.write(s) - - def getvalue(self): - return self.buffer.getvalue() - - def isatty(self): - return False - Modified: pypy/dist/pypy/tool/build/config.py ============================================================================== --- pypy/dist/pypy/tool/build/config.py (original) +++ pypy/dist/pypy/tool/build/config.py Thu Dec 14 23:09:47 2006 @@ -25,7 +25,7 @@ # settings for the server projectname = 'pypy' -buildpath = packageparent.join('/pypy/tool/build/builds') +buildpath = packageparent.ensure('/pypy/tool/build/builds', dir=True) mailhost = 'localhost' mailport = 25 mailfrom = 'pypybuilds at codespeak.net' Added: pypy/dist/pypy/tool/build/outputbuffer.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/tool/build/outputbuffer.py Thu Dec 14 23:09:47 2006 @@ -0,0 +1,23 @@ +try: + from cStringIO import StringIO +except ImportError: + from StringIO import StringIO + +class OutputBuffer(object): + def __init__(self, print_channel=None): + self.print_channel = print_channel + self.buffer = StringIO() + + def write(self, s): + self.buffer.write(s) + if self.print_channel: + self.print_channel.write(s) + if hasattr(self.print_channel, 'flush'): + self.print_channel.flush() + + def getvalue(self): + return self.buffer.getvalue() + + def isatty(self): + return False + Added: pypy/dist/pypy/tool/build/test/test_outputbuffer.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/tool/build/test/test_outputbuffer.py Thu Dec 14 23:09:47 2006 @@ -0,0 +1,22 @@ +import sys +from StringIO import StringIO +from pypy.tool.build.outputbuffer import OutputBuffer + +def test_output_buffer(): + b = OutputBuffer() + sys.stdout = b + try: + print 'foo' + finally: + sys.stdout = sys.__stdout__ + assert b.getvalue() == 'foo\n' + + s = StringIO() + b = OutputBuffer(s) + sys.stdout = b + try: + print 'bar' + finally: + sys.stdout = sys.__stdout__ + assert b.getvalue() == s.getvalue() == 'bar\n' + From arigo at codespeak.net Fri Dec 15 10:03:56 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 15 Dec 2006 10:03:56 +0100 (CET) Subject: [pypy-svn] r35773 - pypy/dist/pypy/jit/codegen/i386 Message-ID: <20061215090356.ACB0110077@code0.codespeak.net> Author: arigo Date: Fri Dec 15 10:03:54 2006 New Revision: 35773 Modified: pypy/dist/pypy/jit/codegen/i386/viewcode.py Log: Speed up one of the algorithms to avoid a slow quadratic loop. Add a progress bar to the other slow part, disassembling. Modified: pypy/dist/pypy/jit/codegen/i386/viewcode.py ============================================================================== --- pypy/dist/pypy/jit/codegen/i386/viewcode.py (original) +++ pypy/dist/pypy/jit/codegen/i386/viewcode.py Fri Dec 15 10:03:54 2006 @@ -10,6 +10,7 @@ import autopath import operator, sys, os, re, py +from bisect import bisect_left # don't use pypy.tool.udir here to avoid removing old usessions which # might still contain interesting executables @@ -81,11 +82,14 @@ self.addr = addr self.data = data + def touches(self, other): + return (self .addr < other.addr + len(other.data) and + other.addr < self .addr + len(self.data)) + def update(self, other): if other.addr < self.addr: delta = self.addr - other.addr self.addr -= delta - self.offset += delta self.data = '\x00'*delta + self.data ofs1 = other.addr - self.addr ofs2 = ofs1 + len(other.data) @@ -163,13 +167,15 @@ addr = baseaddr + offset data = pieces[3].replace(':', '').decode('hex') coderange = CodeRange(self, addr, data) - # XXX sloooooooow! - for r in self.ranges: - if addr < r.addr+len(r.data) and r.addr < addr+len(data): - r.update(coderange) - break - else: - self.ranges.append(coderange) + i = bisect_left(self.ranges, coderange) + j = i + while i>0 and coderange.touches(self.ranges[i-1]): + coderange.update(self.ranges[i-1]) + i -= 1 + while j= fnext: + sys.stderr.write("%d%%" % int(f*100.0)) + fnext += 0.1 + sys.stderr.write(".") + sys.stderr.write("100%\n") # split blocks at labeltargets - # XXX slooooow! t = self.labeltargets #print t for r in self.ranges: From antocuni at codespeak.net Fri Dec 15 10:15:30 2006 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Fri, 15 Dec 2006 10:15:30 +0100 (CET) Subject: [pypy-svn] r35774 - pypy/dist/pypy/translator/goal Message-ID: <20061215091530.14F161007A@code0.codespeak.net> Author: antocuni Date: Fri Dec 15 10:15:29 2006 New Revision: 35774 Modified: pypy/dist/pypy/translator/goal/bench-unix.py Log: compute pypy.net code size correctly. Modified: pypy/dist/pypy/translator/goal/bench-unix.py ============================================================================== --- pypy/dist/pypy/translator/goal/bench-unix.py (original) +++ pypy/dist/pypy/translator/goal/bench-unix.py Fri Dec 15 10:15:29 2006 @@ -82,6 +82,8 @@ def get_executables(): #sorted by revision number (highest first) exes = [] for exe in [os.path.join('.', name) for name in os.listdir('.') if name.startswith('pypy-')]: + if os.path.isdir(exe): + continue try: exes.append( (exe.split('-')[2], exe) ) except: @@ -144,8 +146,8 @@ stone = benchmark_result.get_best_result(p) if 'pypy-cli' in exename: + dirname = exename + '-data' codesize = 'N/A' - dirname, _ = os.path.split(exe) exesize = os.path.getsize(os.path.join(dirname, 'main.exe')) else: codesize = os.popen('size "%s" | tail -n1 | cut -f1'%(exename,)).read().strip() From antocuni at codespeak.net Fri Dec 15 10:32:54 2006 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Fri, 15 Dec 2006 10:32:54 +0100 (CET) Subject: [pypy-svn] r35775 - in pypy/dist/pypy/translator/cli: . test Message-ID: <20061215093254.09FB61007C@code0.codespeak.net> Author: antocuni Date: Fri Dec 15 10:32:54 2006 New Revision: 35775 Modified: pypy/dist/pypy/translator/cli/function.py pypy/dist/pypy/translator/cli/test/test_backendopt.py Log: Use the naive version of numeri_switch when one or more cases are negative. Modified: pypy/dist/pypy/translator/cli/function.py ============================================================================== --- pypy/dist/pypy/translator/cli/function.py (original) +++ pypy/dist/pypy/translator/cli/function.py Fri Dec 15 10:32:54 2006 @@ -7,6 +7,7 @@ from pypy.rpython.lltypesystem.lltype import Void from pypy.rpython.ootypesystem import ootype from pypy.translator.oosupport.function import Function as OOFunction +from pypy.translator.oosupport.constant import push_constant from pypy.translator.cli.option import getoption from pypy.translator.cli.cts import CTS from pypy.translator.cli.opcodes import opcodes @@ -16,7 +17,7 @@ from pypy.translator.cli.support import log from pypy.translator.cli.ilgenerator import CLIBaseGenerator -USE_LAST = False +USE_LAST = True class NativeExceptionHandler(object): def begin_try(self): @@ -206,6 +207,7 @@ def render_numeric_switch(self, block): cases = {} + naive = False for link in block.exits: if link.exitcase == "default": default = link, self.next_label('switch') @@ -214,12 +216,21 @@ value = ord(link.exitcase) else: value = link.exitcase - assert value >= 0 + if value < 0: + naive = True + break cases[value] = link, self.next_label('switch') - max_case = max(cases.keys()) + try: + max_case = max(cases.keys()) + except ValueError: + max_case = 0 if max_case > 4096: # XXX: how to find a good way to determine whether to use switch? - raise NotImplementedError # TODO + naive = True + + if naive: + self.render_numeric_switch_naive(block) + return targets = [] for i in xrange(max_case+1): @@ -237,6 +248,17 @@ self._setup_link(link) self.generator.branch_unconditionally(target_label) + def render_numeric_switch_naive(self, block): + for link in block.exits: + target_label = self._get_block_name(link.target) + self._setup_link(link) + if link.exitcase == 'default': + self.ilasm.opcode('br', target_label) + else: + push_constant(self.db, block.exitswitch.concretetype, link.exitcase, self) + self.generator.load(block.exitswitch) + self.ilasm.opcode('beq', target_label) + # Those parts of the generator interface that are function # specific Modified: pypy/dist/pypy/translator/cli/test/test_backendopt.py ============================================================================== --- pypy/dist/pypy/translator/cli/test/test_backendopt.py (original) +++ pypy/dist/pypy/translator/cli/test/test_backendopt.py Fri Dec 15 10:32:54 2006 @@ -20,3 +20,17 @@ def test_ulonglong_switch(self): py.test.skip('Not yet supported') + + def test_switch_naive(self): + def fn(x): + if x == -1: + return 3 + elif x == 3: + return 9 + elif x == 9: + return -1 + return 42 + codegenerator = self.CodeGenerator() + fn = codegenerator.getcompiled(fn, [int]) + for x in (-5,-1,0,3,9,27,48): + assert fn(x) == fn(x) From arigo at codespeak.net Fri Dec 15 10:39:48 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 15 Dec 2006 10:39:48 +0100 (CET) Subject: [pypy-svn] r35776 - pypy/dist/pypy/module/_stackless/test Message-ID: <20061215093948.DB56810079@code0.codespeak.net> Author: arigo Date: Fri Dec 15 10:39:47 2006 New Revision: 35776 Modified: pypy/dist/pypy/module/_stackless/test/test_stackless.py Log: Skip test_stackless. Waiting for stackless_new.py to become stackless.py. This test should be moved to pypy/lib/ too. Modified: pypy/dist/pypy/module/_stackless/test/test_stackless.py ============================================================================== --- pypy/dist/pypy/module/_stackless/test/test_stackless.py (original) +++ pypy/dist/pypy/module/_stackless/test/test_stackless.py Fri Dec 15 10:39:47 2006 @@ -1,6 +1,8 @@ from pypy.conftest import gettestobjspace, option from py.test import skip +skip("rewrite of stackless.py in progress, see stackless_new.py") + class AppTest_Stackless: From mwh at codespeak.net Fri Dec 15 10:57:35 2006 From: mwh at codespeak.net (mwh at codespeak.net) Date: Fri, 15 Dec 2006 10:57:35 +0100 (CET) Subject: [pypy-svn] r35777 - pypy/dist/pypy/rpython/test Message-ID: <20061215095735.426911007B@code0.codespeak.net> Author: mwh Date: Fri Dec 15 10:57:34 2006 New Revision: 35777 Modified: pypy/dist/pypy/rpython/test/test_rpbc.py Log: remove an ooskip -- the test passes Modified: pypy/dist/pypy/rpython/test/test_rpbc.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_rpbc.py (original) +++ pypy/dist/pypy/rpython/test/test_rpbc.py Fri Dec 15 10:57:34 2006 @@ -1444,7 +1444,6 @@ assert res == 42 def test_specialize_functionarg(self): - self._skip_oo("crashes in funny ways") def f(x, y): return x + y def g(x, y, z): From arigo at codespeak.net Fri Dec 15 10:58:32 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 15 Dec 2006 10:58:32 +0100 (CET) Subject: [pypy-svn] r35778 - pypy/dist/pypy/doc Message-ID: <20061215095832.DE7FC1007C@code0.codespeak.net> Author: arigo Date: Fri Dec 15 10:58:29 2006 New Revision: 35778 Modified: pypy/dist/pypy/doc/index.txt pypy/dist/pypy/doc/rtyper.txt Log: Links. Modified: pypy/dist/pypy/doc/index.txt ============================================================================== --- pypy/dist/pypy/doc/index.txt (original) +++ pypy/dist/pypy/doc/index.txt Fri Dec 15 10:58:29 2006 @@ -51,8 +51,8 @@ `bytecode interpreter`_ explains the basic mechanisms of the bytecode interpreter and virtual machine. -`translation`_ offers the beginnings of documentation -about our low level code generator backends. +`translation`_ is a detailed overview of our translation process. The +rtyper_ is the largest component of our translation process. `dynamic-language translation`_ is a paper that describes the translation process, especially the flow object space @@ -319,6 +319,7 @@ .. _`jit backends`: jit.html#backends .. _`hint-annotator`: jit.html#hint-annotator .. _`timeshifter`: jit.html#timeshifter +.. _rtyper: rtyper.html .. _`low-level type system`: rtyper.html#low-level-type .. _`object-oriented type system`: rtyper.html#oo-type .. _`Stackless Transform`: translation.html#the-stackless-transform Modified: pypy/dist/pypy/doc/rtyper.txt ============================================================================== --- pypy/dist/pypy/doc/rtyper.txt (original) +++ pypy/dist/pypy/doc/rtyper.txt Fri Dec 15 10:58:29 2006 @@ -717,7 +717,7 @@ The LLInterpreter is a simple piece of code that is able to interpret flow graphs. This is very useful for testing purposes, especially if you work on -the `RPython Typer`_. The most useful interface for it is the ``interpret`` +the RPython Typer. The most useful interface for it is the ``interpret`` function in the file `pypy/rpython/test/test_llinterp.py`_. It takes as arguments a function and a list of arguments with which the function is supposed to be called. Then it generates the flow graph, annotates it @@ -759,5 +759,4 @@ .. _annotator: translation.html#the-annotation-pass .. _llvm: translation.html#the-llvm-back-end -.. _`rpython typer`: .. include:: _ref.txt From mwh at codespeak.net Fri Dec 15 11:09:53 2006 From: mwh at codespeak.net (mwh at codespeak.net) Date: Fri, 15 Dec 2006 11:09:53 +0100 (CET) Subject: [pypy-svn] r35779 - pypy/dist/pypy/rpython/lltypesystem Message-ID: <20061215100953.F219D10074@code0.codespeak.net> Author: mwh Date: Fri Dec 15 11:09:53 2006 New Revision: 35779 Modified: pypy/dist/pypy/rpython/lltypesystem/rpbc.py Log: cast the function-representing char to an int before using it as an array index (which worked when compiled to c, of course :-) Modified: pypy/dist/pypy/rpython/lltypesystem/rpbc.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/rpbc.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/rpbc.py Fri Dec 15 11:09:53 2006 @@ -289,7 +289,10 @@ def convert_from_to((r_from, r_to), v, llops): c_table = conversion_table(r_from, r_to) if c_table: - return llops.genop('getarrayitem', [c_table, v], + assert v.concretetype is Char + v_int = llops.genop('cast_char_to_int', [v], + resulttype=Signed) + return llops.genop('getarrayitem', [c_table, v_int], resulttype=Char) else: return v From arigo at codespeak.net Fri Dec 15 11:19:26 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 15 Dec 2006 11:19:26 +0100 (CET) Subject: [pypy-svn] r35780 - pypy/dist/pypy/rpython/test Message-ID: <20061215101926.D55841007C@code0.codespeak.net> Author: arigo Date: Fri Dec 15 11:19:24 2006 New Revision: 35780 Modified: pypy/dist/pypy/rpython/test/test_rpbc.py Log: Set withsmallfuncsets to 3 for the tests (as the tests use 2-3 functions at a time, it's more likely to find problems). Add a test, skipped for now in the smallfuncsets case. Modified: pypy/dist/pypy/rpython/test/test_rpbc.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_rpbc.py (original) +++ pypy/dist/pypy/rpython/test/test_rpbc.py Fri Dec 15 11:19:24 2006 @@ -1491,6 +1491,29 @@ res = self.interpret(f, [2]) assert res == False + def test_shrink_pbc_set(self): + def g1(): + return 10 + def g2(): + return 20 + def g3(): + return 30 + def h1(g): # g in {g1, g2} + return 1 + g() + def h2(g): # g in {g1, g2, g3} + return 2 + g() + def f(n): + if n > 5: g = g1 + else: g = g2 + if n % 2: h = h1 + else: h = h2 + res = h(g) + if n > 7: g = g3 + h2(g) + return res + res = self.interpret(f, [7]) + assert res == 11 + class TestLLtype(BaseTestRPBC, LLRtypeMixin): pass @@ -1757,12 +1780,16 @@ def setup_class(cls): from pypy.config.pypyoption import get_pypy_config cls.config = get_pypy_config(translating=True) - cls.config.translation.withsmallfuncsets = 10 + cls.config.translation.withsmallfuncsets = 3 def interpret(self, fn, args, **kwds): kwds['config'] = self.config return TestLLtype.interpret(self, fn, args, **kwds) + def test_shrink_pbc_set(self): + # fails with config.translation.withsmallfuncsets == 3 + py.test.skip("XXX not implemented") + def test_smallfuncsets_basic(): from pypy.translator.translator import TranslationContext, graphof from pypy.config.pypyoption import get_pypy_config From guido at codespeak.net Fri Dec 15 11:48:12 2006 From: guido at codespeak.net (guido at codespeak.net) Date: Fri, 15 Dec 2006 11:48:12 +0100 (CET) Subject: [pypy-svn] r35781 - pypy/dist/pypy/tool/build/test Message-ID: <20061215104812.22B2B10088@code0.codespeak.net> Author: guido Date: Fri Dec 15 11:48:10 2006 New Revision: 35781 Modified: pypy/dist/pypy/tool/build/test/test_client.py Log: Hrmph, forgot to remove this test... Modified: pypy/dist/pypy/tool/build/test/test_client.py ============================================================================== --- pypy/dist/pypy/tool/build/test/test_client.py (original) +++ pypy/dist/pypy/tool/build/test/test_client.py Fri Dec 15 11:48:10 2006 @@ -80,20 +80,3 @@ assert br in c1.refused assert c1.busy_on == None -def test_output_buffer(): - b = client.OutputBuffer() - sys.stdout = b - try: - print 'foo' - finally: - sys.stdout = sys.__stdout__ - assert b.getvalue() == 'foo\n' - s = py.std.StringIO.StringIO() - b = client.OutputBuffer(s) - sys.stdout = b - try: - print 'bar' - finally: - sys.stdout = sys.__stdout__ - assert b.getvalue() == s.getvalue() == 'bar\n' - From antocuni at codespeak.net Fri Dec 15 11:50:51 2006 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Fri, 15 Dec 2006 11:50:51 +0100 (CET) Subject: [pypy-svn] r35782 - in pypy/dist/pypy/translator: c/test cli cli/test oosupport Message-ID: <20061215105051.BA84410088@code0.codespeak.net> Author: antocuni Date: Fri Dec 15 11:50:50 2006 New Revision: 35782 Modified: pypy/dist/pypy/translator/c/test/test_backendoptimized.py pypy/dist/pypy/translator/cli/function.py pypy/dist/pypy/translator/cli/ilgenerator.py pypy/dist/pypy/translator/cli/test/test_backendopt.py pypy/dist/pypy/translator/oosupport/function.py pypy/dist/pypy/translator/oosupport/metavm.py Log: Make render_numeric_switch_naive backend-indipendent and move it to oosupport. Added support for *LongLong switches in gencli. Modified: pypy/dist/pypy/translator/c/test/test_backendoptimized.py ============================================================================== --- pypy/dist/pypy/translator/c/test/test_backendoptimized.py (original) +++ pypy/dist/pypy/translator/c/test/test_backendoptimized.py Fri Dec 15 11:50:50 2006 @@ -144,7 +144,7 @@ return 0 codegenerator = self.CodeGenerator() fn = codegenerator.getcompiled(f, [r_ulonglong]) - for x in (0,1,2,3,9,27,48, -9): + for x in (0,1,2,3,9,27,48, r_ulonglong(-9)): assert fn(x) == f(x) def test_chr_switch(self): Modified: pypy/dist/pypy/translator/cli/function.py ============================================================================== --- pypy/dist/pypy/translator/cli/function.py (original) +++ pypy/dist/pypy/translator/cli/function.py Fri Dec 15 11:50:50 2006 @@ -206,6 +206,12 @@ self.ilasm.opcode('ret') def render_numeric_switch(self, block): + if block.exitswitch.concretetype in (ootype.SignedLongLong, ootype.UnsignedLongLong): + # TODO: it could be faster to check is the values fit in + # 32bit, and perform a cast in that case + self.render_numeric_switch_naive(block) + return + cases = {} naive = False for link in block.exits: @@ -248,17 +254,6 @@ self._setup_link(link) self.generator.branch_unconditionally(target_label) - def render_numeric_switch_naive(self, block): - for link in block.exits: - target_label = self._get_block_name(link.target) - self._setup_link(link) - if link.exitcase == 'default': - self.ilasm.opcode('br', target_label) - else: - push_constant(self.db, block.exitswitch.concretetype, link.exitcase, self) - self.generator.load(block.exitswitch) - self.ilasm.opcode('beq', target_label) - # Those parts of the generator interface that are function # specific Modified: pypy/dist/pypy/translator/cli/ilgenerator.py ============================================================================== --- pypy/dist/pypy/translator/cli/ilgenerator.py (original) +++ pypy/dist/pypy/translator/cli/ilgenerator.py Fri Dec 15 11:50:50 2006 @@ -350,6 +350,9 @@ def branch_conditionally(self, cond, target_label): self.ilasm.branch_if(cond, target_label) + def branch_if_equal(self, target_label): + self.ilasm.opcode('beq', target_label) + def push_primitive_constant(self, TYPE, value): ilasm = self.ilasm if TYPE is ootype.Void: Modified: pypy/dist/pypy/translator/cli/test/test_backendopt.py ============================================================================== --- pypy/dist/pypy/translator/cli/test/test_backendopt.py (original) +++ pypy/dist/pypy/translator/cli/test/test_backendopt.py Fri Dec 15 11:50:50 2006 @@ -15,11 +15,6 @@ return compile_function(fn, annotation, backend_opt=self.backend_opt) class TestOptimizedSwitchTestCase(CTestCompat, c_TestTypedOptimizedSwitchTestCase): - def test_longlong_switch(self): - py.test.skip('Not yet supported') - - def test_ulonglong_switch(self): - py.test.skip('Not yet supported') def test_switch_naive(self): def fn(x): Modified: pypy/dist/pypy/translator/oosupport/function.py ============================================================================== --- pypy/dist/pypy/translator/oosupport/function.py (original) +++ pypy/dist/pypy/translator/oosupport/function.py Fri Dec 15 11:50:50 2006 @@ -1,3 +1,8 @@ +import py +from pypy.tool.ansi_print import ansi_log +log = py.log.Producer("oosupport") +py.log.setconsumer("oosupport", ansi_log) + from pypy.objspace.flow import model as flowmodel from pypy.rpython.ootypesystem import ootype from pypy.translator.oosupport.metavm import InstructionList @@ -177,7 +182,9 @@ self.generator.branch_unconditionally(target_label) elif block.exitswitch.concretetype is ootype.Bool: self.render_bool_switch(block) - elif block.exitswitch.concretetype in (ootype.Signed, ootype.Unsigned, ootype.Char, ootype.UniChar): + elif block.exitswitch.concretetype in (ootype.Signed, ootype.SignedLongLong, + ootype.Unsigned, ootype.UnsignedLongLong, + ootype.Char, ootype.UniChar): self.render_numeric_switch(block) else: assert False, 'Unknonw exitswitch type: %s' % block.exitswitch.concretetype @@ -195,7 +202,19 @@ self.generator.branch_conditionally(link.exitcase, target_label) def render_numeric_switch(self, block): - raise NotImplementedError # it's too dependent on the backend to be implemented here + log.WARNING("The default version of render_numeric_switch is *slow*: please override it in the backend") + self.render_numeric_switch_naive(block) + + def render_numeric_switch_naive(self, block): + for link in block.exits: + target_label = self._get_block_name(link.target) + self._setup_link(link) + if link.exitcase == 'default': + self.generator.branch_unconditionally(target_label) + else: + self.generator.push_primitive_constant(block.exitswitch.concretetype, link.exitcase) + self.generator.load(block.exitswitch) + self.generator.branch_if_equal(target_label) def _setup_link(self, link): self.generator.add_comment("Setup link") Modified: pypy/dist/pypy/translator/oosupport/metavm.py ============================================================================== --- pypy/dist/pypy/translator/oosupport/metavm.py (original) +++ pypy/dist/pypy/translator/oosupport/metavm.py Fri Dec 15 11:50:50 2006 @@ -138,6 +138,15 @@ Stack: cond, ... -> ... """ raise NotImplementedError + def branch_if_equal(self, target_label): + """ + Pops two values from the stack and branches to target_label if + they are equal. + + Stack: obj1, obj2, ... -> ... + """ + raise NotImplementedError + def call_graph(self, graph): """ Invokes the function corresponding to the given graph. The arguments to the graph have already been pushed in order From ericvrp at codespeak.net Fri Dec 15 11:54:13 2006 From: ericvrp at codespeak.net (ericvrp at codespeak.net) Date: Fri, 15 Dec 2006 11:54:13 +0100 (CET) Subject: [pypy-svn] r35783 - in pypy/dist/pypy/jit/codegen/llvm: . test Message-ID: <20061215105413.6E72C10088@code0.codespeak.net> Author: ericvrp Date: Fri Dec 15 11:54:11 2006 New Revision: 35783 Modified: pypy/dist/pypy/jit/codegen/llvm/rgenop.py pypy/dist/pypy/jit/codegen/llvm/test/test_genc_ts.py pypy/dist/pypy/jit/codegen/llvm/test/test_genc_vlist.py pypy/dist/pypy/jit/codegen/llvm/test/test_rgenop.py Log: jit/codegen/llvm * fix for same_as() * enabled the passing tests of test_genc_ts.py (skipping the others) * add calling a function of type AddrConst (this caused one rgenop test to fail which I do not understand!) Modified: pypy/dist/pypy/jit/codegen/llvm/rgenop.py ============================================================================== --- pypy/dist/pypy/jit/codegen/llvm/rgenop.py (original) +++ pypy/dist/pypy/jit/codegen/llvm/rgenop.py Fri Dec 15 11:54:11 2006 @@ -410,16 +410,19 @@ #XXX 'cast' has been replaced by many sext/zext/uitofp/... opcodes in the upcoming llvm 2.0. #The lines upto /XXX should be refactored to do the right thing - def op_same_as(self, gv_x): - gv_result = Var(gv_x.type) - self.asm.append(' %s=bitcast %s to %s' % ( - gv_result.operand2(), gv_x.operand(), gv_x.type)) - return gv_result + def genop_same_as(self, kind, gv_x): + if gv_x.is_const: # must always return a var + gv_result = Var(gv_x.type) + self.asm.append(' %s=bitcast %s to %s' % ( + gv_result.operand2(), gv_x.operand(), gv_x.type)) + return gv_result + else: + return gv_x def _cast_to(self, gv_x, restype=None): restype = restype or gv_x.type if restype is gv_x.type: - return self.op_same_as(gv_x) + return self.genop_same_as(None, gv_x) gv_result = Var(restype) self.asm.append(' %s=zext %s to %s' % ( gv_result.operand2(), gv_x.operand(), restype)) @@ -428,7 +431,7 @@ def _trunc_to(self, gv_x, restype=None): restype = restype or gv_x.type if restype is gv_x.type: - return self.op_same_as(gv_x) + return self.genop_same_as(None, gv_x) gv_result = Var(restype) self.asm.append(' %s=trunc %s to %s' % ( gv_result.operand2(), gv_x.operand(), restype)) @@ -632,16 +635,26 @@ gv_result.operand2(), gv_gc_malloc_fnaddr.operand(), gv_size.operand())) #XXX TODO set length field return gv_result - + + def _funcsig_type(self, args_gv, restype): + return '%s (%s)' % (restype, ','.join([a.type for a in args_gv])) + def genop_call(self, sigtoken, gv_fnptr, args_gv): log('%s Builder.genop_call %s,%s,%s' % ( self.block.label, sigtoken, gv_fnptr, [v.operand() for v in args_gv])) argtypes, restype = sigtoken gv_returnvar = Var(restype) - #XXX we probably need to call an address directly if we can't resolve the funcsig + if isinstance(gv_fnptr, AddrConst): + gv_fn = Var(self._funcsig_type(args_gv, restype)) + self.asm.append(' %s=bitcast %s to %s' % ( + gv_fnptr.operand2(), gv_fnptr.operand(), gv_fn.type)) + funcsig = gv_fn.operand() + else: + #XXX we probably need to call an address directly if we can't resolve the funcsig + funcsig = self.rgenop.funcsig[gv_fnptr.value] self.asm.append(' %s=call %s(%s)' % ( gv_returnvar.operand2(), - self.rgenop.funcsig[gv_fnptr.value], + funcsig, ','.join([v.operand() for v in args_gv]))) return gv_returnvar @@ -678,6 +691,9 @@ funcsig = {} #HACK for looking up function signatures funcused = {} #we rename functions when encountered multiple times (for test_branching_compile) + def check_no_open_mc(self): + return True + def end(self): log(' RLLVMGenOp.end') self.blocklist.append(EpilogueBlock()) @@ -743,8 +759,8 @@ return IntConst(lltype.cast_primitive(lltype.Signed, llvalue)) elif isinstance(T, lltype.Ptr): lladdr = llmemory.cast_ptr_to_adr(llvalue) - if T.TO._gckind == 'gc': - self.keepalive_gc_refs.append(lltype.cast_opaque_ptr(llmemory.GCREF, llvalue)) + #if T.TO._gckind == 'gc': + # self.keepalive_gc_refs.append(lltype.cast_opaque_ptr(llmemory.GCREF, llvalue)) return AddrConst(lladdr) else: assert 0, "XXX not implemented" 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 Fri Dec 15 11:54:11 2006 @@ -7,7 +7,6 @@ class LLVMTimeshiftingTestMixin(I386TimeshiftingTestMixin): RGenOp = RLLVMGenOp -py.test.skip("WIP") class TestTimeshiftLLVM(LLVMTimeshiftingTestMixin, test_timeshift.TestTimeshift): @@ -15,5 +14,60 @@ # for the individual tests see # ====> ../../../timeshifter/test/test_timeshift.py - pass + def skip(self): + py.test.skip("WIP") + + #passing... + #test_very_simple = skip + #test_convert_const_to_redbox = skip + #test_simple_opt_const_propagation2 = skip + #test_simple_opt_const_propagation1 = skip + #test_loop_folding = skip + #test_loop_merging = skip + #test_two_loops_merging = skip + #test_convert_greenvar_to_redvar = skip + #test_green_across_split = skip + #test_merge_const_before_return = skip + #test_merge_3_redconsts_before_return = skip + #test_arith_plus_minus = skip + #test_plus_minus_all_inlined = skip + #test_call_simple = skip + #test_call_2 = skip + #test_call_3 = skip + #test_call_4 = skip + #test_void_call = skip + #test_green_call = skip + #test_split_on_green_return = skip + #test_recursive_call = skip + #test_simple_indirect_call = skip + #test_normalize_indirect_call = skip + #test_normalize_indirect_call_more = skip + #test_green_red_mismatch_in_call = skip + #test_red_call_ignored_result = skip + + #failing... + test_simple_struct = skip + test_simple_array = skip + test_degenerated_before_return = skip + test_degenerated_before_return_2 = skip + test_degenerated_at_return = skip + test_degenerated_via_substructure = skip + test_degenerate_with_voids = skip + test_red_virtual_container = skip + test_setarrayitem = skip + test_red_array = skip + test_red_struct_array = skip + test_red_varsized_struct = skip + test_array_of_voids = skip + test_red_propagate = skip + test_red_subcontainer = skip + test_red_subcontainer_cast = skip + test_merge_structures = skip + test_green_with_side_effects = skip + test_recursive_with_red_termination_condition = skip + test_simple_meth = skip + test_simple_red_meth = skip + test_compile_time_const_tuple = skip + test_residual_red_call = skip + test_residual_red_call_with_exc = skip Modified: pypy/dist/pypy/jit/codegen/llvm/test/test_genc_vlist.py ============================================================================== --- pypy/dist/pypy/jit/codegen/llvm/test/test_genc_vlist.py (original) +++ pypy/dist/pypy/jit/codegen/llvm/test/test_genc_vlist.py Fri Dec 15 11:54:11 2006 @@ -3,6 +3,8 @@ from pypy.jit.codegen.llvm.test.test_genc_ts import LLVMTimeshiftingTestMixin +py.test.skip('WIP') + class TestVList(LLVMTimeshiftingTestMixin, test_vlist.TestVList): Modified: pypy/dist/pypy/jit/codegen/llvm/test/test_rgenop.py ============================================================================== --- pypy/dist/pypy/jit/codegen/llvm/test/test_rgenop.py (original) +++ pypy/dist/pypy/jit/codegen/llvm/test/test_rgenop.py Fri Dec 15 11:54:11 2006 @@ -14,6 +14,8 @@ def skip(self): py.test.skip('WIP') + test_fact_compile = skip #XXX Blocked block, introducted by this checkin (I don't understand) + test_switch_direct = skip test_switch_compile = skip From antocuni at codespeak.net Fri Dec 15 11:57:14 2006 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Fri, 15 Dec 2006 11:57:14 +0100 (CET) Subject: [pypy-svn] r35784 - pypy/dist/pypy/translator/cli Message-ID: <20061215105714.712E110089@code0.codespeak.net> Author: antocuni Date: Fri Dec 15 11:57:13 2006 New Revision: 35784 Modified: pypy/dist/pypy/translator/cli/function.py Log: This heuristic makes much more sense. Thanks arigo. Modified: pypy/dist/pypy/translator/cli/function.py ============================================================================== --- pypy/dist/pypy/translator/cli/function.py (original) +++ pypy/dist/pypy/translator/cli/function.py Fri Dec 15 11:57:13 2006 @@ -231,7 +231,7 @@ max_case = max(cases.keys()) except ValueError: max_case = 0 - if max_case > 4096: # XXX: how to find a good way to determine whether to use switch? + if max_case > 3*len(cases) + 10: # the switch is very sparse, better to use the naive version naive = True if naive: From arigo at codespeak.net Fri Dec 15 13:58:30 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 15 Dec 2006 13:58:30 +0100 (CET) Subject: [pypy-svn] r35792 - pypy/dist/pypy/doc Message-ID: <20061215125830.33DDE1007A@code0.codespeak.net> Author: arigo Date: Fri Dec 15 13:58:28 2006 New Revision: 35792 Modified: pypy/dist/pypy/doc/_ref.txt pypy/dist/pypy/doc/draft-jit-outline.txt Log: Started explaining "timeshifting". Modified: pypy/dist/pypy/doc/_ref.txt ============================================================================== --- pypy/dist/pypy/doc/_ref.txt (original) +++ pypy/dist/pypy/doc/_ref.txt Fri Dec 15 13:58:28 2006 @@ -32,6 +32,7 @@ .. _`pypy/jit/codegen/model.py`: ../../pypy/jit/codegen/model.py .. _`jit/hintannotator/`: ../../pypy/jit/hintannotator .. _`jit/timeshifter/`: ../../pypy/jit/timeshifter +.. _`pypy/jit/timeshifter/rvalue.py`: ../../pypy/jit/timeshifter/rvalue.py .. _`jit/tl/`: ../../pypy/jit/tl .. _`lang/`: ../../pypy/lang .. _`lang/js/`: ../../pypy/lang/js Modified: pypy/dist/pypy/doc/draft-jit-outline.txt ============================================================================== --- pypy/dist/pypy/doc/draft-jit-outline.txt (original) +++ pypy/dist/pypy/doc/draft-jit-outline.txt Fri Dec 15 13:58:28 2006 @@ -2,6 +2,9 @@ JIT Generation in PyPy ======================= +.. contents:: +.. sectnum:: + Introduction ============= @@ -344,12 +347,16 @@ regular RPython object reference in the RPython source). The hint-annotation will then propagate a "deepfrozen" flag on the annotation attached to ``v2``. If ``v2`` is green, a ``getfield(v2, -"name")`` operation then also returns a green. Moreover, the result of -the ``getfield`` is also itself "deepfrozen". We decided to implement -recursive freezing and not one-level-only freezing, as the latter seems -more fragile with respect to changes both in the RPython source and in -the way the source maps to low-level graphs; but variants could easily -be implemented if needed. +"name")`` operation then also returns a green. The flag is also +relevant if ``v2`` is red, as we will see in `Red and Green Operations`_ +below. + +As the name suggests, the result of a ``getfield`` is itself +"deepfrozen" if the structure was. We decided to implement recursive +freezing and not one-level-only freezing, as the latter seems more +fragile with respect to changes both in the RPython source and in the +way the source maps to low-level graphs; but variants could easily be +implemented if needed. Blue containers @@ -365,21 +372,161 @@ Timeshifting: transforming interpreter into compilers ====================================================== -intro and basics - -Basics --------- - -...red vs green operations... +Once binding times (colors) have been assigned to all variables in a +family of control flow graphs, the next step is to mutate the graphs +accordingly. This process is called *timeshifting*, because it changes +the time at which the graphs are meant to be run. So far, the graphs +implemented some kind of interpreter; they were meant to execute at +run-time, and directly computed the intended result and side-effects. +After timeshifting, the graphs are logically very different: they are +intended to be executed at compile-time, and their only side effects is +to produce residual code. The residual code itself can later be +executed at run-time. + +Despite the difference, though, the timeshifted graphs are formally +close to the original graphs. The rest of this section describes this +timeshifting process in more detail. + + +Red and Green Operations +-------------------------- + +The basic idea of timeshifting is how to implement variables based +on their color: + +* The green variables are the compile-time variables. Their values are + meant to be available during compile-time already. A variable that + used to contain e.g. an integer at run-time in the original graph, and + which the hint-annotator found to be green, is turned into a variable + that contains an integer again, but now at compile-time. In other + words, timeshifting leaves green variables untouched - they are + identical in the original and in the timeshifted graph. + +* The red (run-time) variables on the other hand cannot stay unmodified + in the timeshifted graph, because no actual value is available for + them during compile-time. They are replaced by the notion of "red + box": a red box is a small object that describes where, in the + residual code, the value will be stored at run-time. Multiple red + variables are turned into multiple red boxes, which are used to + distinguish the residual storage location for each of them. + +The basic feature of each red box is to provide a field ``genvar``, +which is a backend-specific object that represents a machine code +operand - either a value location (e.g. the register where it is stored) +or a constant (an immediate). Constants are used for red boxes whose +value is, after all, known at compile-time. This can occur even though +the corresponding variable in the graph was red; it is the case when the +hint-annotator cannot tell statically that a given variable will always +contain a compile-time constant, even though it might dynamically be +found to contain one at a particular point in (compile-)time. In +Partial Evaluation terminology, the timeshifted graphs are performing +some *on-line* partial evaluation in addition to the off-line job +enabled by the hint-annotator. + +In addition to the variables, all operations of the original graphs need +to be checked: + +* If an operation has no side effect or other run-time dependency, and + if it only involves green operands, then it can stay unmodified in the + graph. In this case, the operation that was run-time in the original + graph becomes a compile-time operation, and it will never be generated + in the residual code. (This is the case that makes the whole approach + worthwhile: some operations become purely compile-time.) + +* In all other cases, the operation might have to be generated in the + residual code. In the timeshifted graph, it is replaced by a call to + a helper. There is one such helper per operation, which takes red + boxes as its arguments, and asks the backend to generate the + corresponding residual operation on the ``genvar`` of the red boxes. + The backend answers by giving a new ``genvar``, which is the location + of the result, and the helper puts it into a new red box, which is + returned to the timeshifted graph as the result of the call. + +Additionally, the helper for some operations checks if all arguments are +red boxes containing constants, and if so just returns a red box +containing the result without producing any residual code. A particular +case to note is that of the ``getfield`` operation: when applied on a +constant red box, the field can sometimes be directly read out of the +structure at compile-time - this decision is based on the static `Deep +freezing`_ analysis performed by the hint-annotator. + + +Support code +-------------- + +To implement red boxes, we have written a family of support classes in +`pypy/jit/timeshifter/rvalue.py`_: IntRedBox, DoubleRedBox and +PtrRedBox. They are used, respectively, for integral values of any +size, for floating-point values, and for pointers and addresses. As we +will see below, these classes support a number of additional features, +particularly PtrRedBox. + +These classes are regular RPython classes that are translated to +low-level and linked with the rest of the program. The same holds for +the helper functions that inspect red boxes and generate residual +operations. We make extensive use of this technique (described in more +detail in VMC_): all the complex support code that is needed for the +timeshifted graphs is implemented as regular RPython code and linked +with the rest of the program, by inserting calls to these helpers from +the timeshifted graphs, and also (as in the red box case) by putting +variables in the graphs whose types are (the low-level representation +of) instances of helper RPython classes. + +The amount of support code is quite extensive, as it includes the whole +machine code backend as well: when helpers need to produce residual +code, they do so through a well-defined API on classes that are provided +by one of our JIT backends. (This will be described in more details in +the Backends_ section.) All this support code can be arbitrarily +complex RPython code, which allows us to experiment quite freely. + + +Two-Phases Transformation +--------------------------- + +Concretely, the process of timeshiting replaces some variables with +fresh variables of new types, and replaces some operations with calls to +helper functions. This is very similar to what the `RPython Typer`_ +does during a normal translation. The latter replaces RPython-level +variables and operations with low-level variables and operations and +calls to helpers; it is guided by the annotations produced by the +regular type inference. The former does the same, except that the input +is already low-level operations, and the annotations are colors, +produced by the hint-annotator. + +In light of this close analogy, we have implemented the timeshifter +based on the RTyper. This gives us direct benefits, like automatic +conversions for operation arguments or along links. For example, if an +operation takes two arguments, but one of them is red and the other +green, then the whole operation must classify as "red" and be replaced +by a call to the corresponding helper. This helper expects two red +boxes as arguments, though. The red argument is a red box in the +timeshifted graph, but not the green one. Reusing the RTyper logic, the +necessary conversion (creating a red box and putting the green value +into it as an immediate) is inserted automatically in cases like this +one. + +Unlike the regular RTyper, though, the timeshifter is faced with an +additional difficulty that will only become apparent in the sequel: in +addition to the local replacement of variables and operations, it also +needs to modify the control flow of the graph. + +The approach that we have taken is in two phases: + +* The graphs are first transformed "manually". This phase modifies the + control flow and adds pseudo-operations in key places. In some sense, + all the interesting large-scale issues, experiments and solutions with + timeshifting a graph are present in this transformation. The + pseudo-operations are placeholders for bookkeeping operations like + saving local variables into JIT state structures, scheduling various + parts of the compilation, and so on. This phase preserves the colors; + its output is graphs that look like pseudo-code, convenient to inspect + in the graph viewer for debugging and explanation purposes. + +* The modified RTyper (called "HRTyper") is applied in a second phase. + It replaces variables and operations locally as described above. The + pseudo-operations are replaced along with all the other ones, and + become calls to helpers. -XXX Note that the "deepfrozen" flag is used at compile-time on red -values too, to influence the details of how residual ``getfield`` -operations should be generated. - -Transform vs hrtyping ------------------------ - -... Split and Merges -------------------- @@ -435,9 +582,14 @@ ... + +.. _VMC: http://codespeak.net/svn/pypy/extradoc/talk/dls2006/pypy-vm-construction.pdf .. _`RPython`: coding-guide.html#rpython +.. _`RPython Typer`: translation.html#rpython-typer .. _`low-level graphs`: rtyper.html .. _`pointer-and-structures-like objects`: rtyper.html#low-level-types .. _`annotator`: dynamic-language-translation.html .. _`specialization of functions`: dynamic-language-translation.html#specialization .. _Psyco: http://psyco.sourceforge.net + +.. include:: _ref.txt From pedronis at codespeak.net Fri Dec 15 14:26:44 2006 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Fri, 15 Dec 2006 14:26:44 +0100 (CET) Subject: [pypy-svn] r35796 - pypy/dist/pypy/doc Message-ID: <20061215132644.06B0610084@code0.codespeak.net> Author: pedronis Date: Fri Dec 15 14:26:42 2006 New Revision: 35796 Modified: pypy/dist/pypy/doc/draft-jit-outline.txt Log: small fix, some exapnding rewording. Modified: pypy/dist/pypy/doc/draft-jit-outline.txt ============================================================================== --- pypy/dist/pypy/doc/draft-jit-outline.txt (original) +++ pypy/dist/pypy/doc/draft-jit-outline.txt Fri Dec 15 14:26:42 2006 @@ -391,8 +391,9 @@ Red and Green Operations -------------------------- -The basic idea of timeshifting is how to implement variables based -on their color: +The basic idea of timeshifting is to transform operations depending on +the color of their operands. Variables themselves need to be represented +based on their color: * The green variables are the compile-time variables. Their values are meant to be available during compile-time already. A variable that @@ -424,7 +425,7 @@ enabled by the hint-annotator. In addition to the variables, all operations of the original graphs need -to be checked: +to be checked and accordingly transformed: * If an operation has no side effect or other run-time dependency, and if it only involves green operands, then it can stay unmodified in the @@ -483,7 +484,7 @@ Two-Phases Transformation --------------------------- -Concretely, the process of timeshiting replaces some variables with +Concretely, the process of timeshifting replaces some variables with fresh variables of new types, and replaces some operations with calls to helper functions. This is very similar to what the `RPython Typer`_ does during a normal translation. The latter replaces RPython-level From cfbolz at codespeak.net Fri Dec 15 14:27:08 2006 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Fri, 15 Dec 2006 14:27:08 +0100 (CET) Subject: [pypy-svn] r35797 - pypy/extradoc/eu-report Message-ID: <20061215132708.6199810088@code0.codespeak.net> Author: cfbolz Date: Fri Dec 15 14:26:52 2006 New Revision: 35797 Added: pypy/extradoc/eu-report/D07.1_Massive_Parallelism_and_Translation_Aspects-interim-2006-12-15.pdf Removed: pypy/extradoc/eu-report/D07.1_Massive_Parallelism_and_Translation_Aspects-interim-2006-07-25.pdf Log: update version of D07 Added: pypy/extradoc/eu-report/D07.1_Massive_Parallelism_and_Translation_Aspects-interim-2006-12-15.pdf ============================================================================== --- (empty file) +++ pypy/extradoc/eu-report/D07.1_Massive_Parallelism_and_Translation_Aspects-interim-2006-12-15.pdf Fri Dec 15 14:26:52 2006 @@ -0,0 +1,5542 @@ +%PDF-1.4 +5 0 obj +<< /S /GoTo /D (section.1) >> +endobj +8 0 obj +(Executive Summary) +endobj +9 0 obj +<< /S /GoTo /D (section.2) >> +endobj +12 0 obj +(Introduction) +endobj +13 0 obj +<< /S /GoTo /D (subsection.2.1) >> +endobj +16 0 obj +(Purpose of this Document) +endobj +17 0 obj +<< /S /GoTo /D (subsection.2.2) >> +endobj +20 0 obj +(Scope of this Document) +endobj +21 0 obj +<< /S /GoTo /D (subsection.2.3) >> +endobj +24 0 obj +(Related Documents) +endobj +25 0 obj +<< /S /GoTo /D (section.3) >> +endobj +28 0 obj +(Stackless Features) +endobj +29 0 obj +<< /S /GoTo /D (subsection.3.1) >> +endobj +32 0 obj +(Introduction: Stackless Features for RPython Programs) +endobj +33 0 obj +<< /S /GoTo /D (subsection.3.2) >> +endobj +36 0 obj +(The Stackless Transformation) +endobj +37 0 obj +<< /S /GoTo /D (subsubsection.3.2.1) >> +endobj +40 0 obj +(Saving and Resuming Frames) +endobj +41 0 obj +<< /S /GoTo /D (subsubsection.3.2.2) >> +endobj +44 0 obj +(``Unbounded'' Stack) +endobj +45 0 obj +<< /S /GoTo /D (subsubsection.3.2.3) >> +endobj +48 0 obj +(Interface to Explicit Stack Manipulations) +endobj +49 0 obj +<< /S /GoTo /D (subsubsection.3.2.4) >> +endobj +52 0 obj +(Resume Points) +endobj +53 0 obj +<< /S /GoTo /D (subsubsection.3.2.5) >> +endobj +56 0 obj +(Performance Impact) +endobj +57 0 obj +<< /S /GoTo /D (subsection.3.3) >> +endobj +60 0 obj +(Application Level Interface) +endobj +61 0 obj +<< /S /GoTo /D (subsubsection.3.3.1) >> +endobj +64 0 obj +(Coroutines) +endobj +65 0 obj +<< /S /GoTo /D (subsubsection.3.3.2) >> +endobj +68 0 obj +(Tasklets and Channels) +endobj +69 0 obj +<< /S /GoTo /D (subsubsection.3.3.3) >> +endobj +72 0 obj +(Greenlets) +endobj +73 0 obj +<< /S /GoTo /D (subsubsection.3.3.4) >> +endobj +76 0 obj +(Coroutine Pickling) +endobj +77 0 obj +<< /S /GoTo /D (subsubsection.3.3.5) >> +endobj +80 0 obj +(Coroutine Cloning) +endobj +81 0 obj +<< /S /GoTo /D (subsubsection.3.3.6) >> +endobj +84 0 obj +(Composability) +endobj +85 0 obj +<< /S /GoTo /D (subsubsection.3.3.7) >> +endobj +88 0 obj +(Microbenchmarks of Stackless Features) +endobj +89 0 obj +<< /S /GoTo /D (subsection.3.4) >> +endobj +92 0 obj +(Practical Uses of Massive Parallelism) +endobj +93 0 obj +<< /S /GoTo /D (subsection.3.5) >> +endobj +96 0 obj +(Related Work) +endobj +97 0 obj +<< /S /GoTo /D (section.4) >> +endobj +100 0 obj +(Optimizations and Memory Management) +endobj +101 0 obj +<< /S /GoTo /D (subsection.4.1) >> +endobj +104 0 obj +(Optimizations) +endobj +105 0 obj +<< /S /GoTo /D (subsubsection.4.1.1) >> +endobj +108 0 obj +(Function Inlining) +endobj +109 0 obj +<< /S /GoTo /D (subsubsection.4.1.2) >> +endobj +112 0 obj +(Malloc Removal) +endobj +113 0 obj +<< /S /GoTo /D (subsubsection.4.1.3) >> +endobj +116 0 obj +(Escape Analysis and Stack Allocation) +endobj +117 0 obj +<< /S /GoTo /D (subsubsection.4.1.4) >> +endobj +120 0 obj +(Pointer Tagging) +endobj +121 0 obj +<< /S /GoTo /D (subsection.4.2) >> +endobj +124 0 obj +(Memory Management) +endobj +125 0 obj +<< /S /GoTo /D (subsubsection.4.2.1) >> +endobj +128 0 obj +(The GC Transformer) +endobj +129 0 obj +<< /S /GoTo /D (subsubsection.4.2.2) >> +endobj +132 0 obj +(Using The Conservative Boehm Collector) +endobj +133 0 obj +<< /S /GoTo /D (subsubsection.4.2.3) >> +endobj +136 0 obj +(Reference Counting) +endobj +137 0 obj +<< /S /GoTo /D (subsubsection.4.2.4) >> +endobj +140 0 obj +(The GC Construction and Testing Framework) +endobj +141 0 obj +<< /S /GoTo /D (subsubsection.4.2.5) >> +endobj +144 0 obj +(The Mark-and-Sweep Collector) +endobj +145 0 obj +<< /S /GoTo /D (subsubsection.4.2.6) >> +endobj +148 0 obj +(Performance \046 Future work) +endobj +149 0 obj +<< /S /GoTo /D (subsection.4.3) >> +endobj +152 0 obj +(Related Work) +endobj +153 0 obj +<< /S /GoTo /D (section.5) >> +endobj +156 0 obj +(Conclusion) +endobj +157 0 obj +<< /S /GoTo /D (section.6) >> +endobj +160 0 obj +(Glossary of Abbreviations) +endobj +161 0 obj +<< /S /GoTo /D (subsection.6.1) >> +endobj +164 0 obj +(Technical Abbreviations:) +endobj +165 0 obj +<< /S /GoTo /D (subsection.6.2) >> +endobj +168 0 obj +(Partner Acronyms:) +endobj +169 0 obj +<< /S /GoTo /D [170 0 R /Fit ] >> +endobj +174 0 obj << +/Length 1218 +/Filter /FlateDecode +>> +stream +x??W?r?6}?W?Q? ?A???%???????1A?`?????&?_)?8?"R?!?????GkX?2"??D\H/GVc?1?J??P?4?????Q@`????p?????$??Gw???7?G???A?F?.??{?_O?m??????(aR??D???? ??????id<?iT?xB#???b4? ?xEeD1,?T??????????l>?i??WSc????????|??"Hb ???A0C?q?vp)???b*?$?"?!?wH?O*$?z?!=?6?v?Rk$???*f??t???????8'?M"???q~?5Y????r?Wk???=????x??,? ???|?Vn?[?? +0a_n?j??k??`J??G???r?b?TDx????c?-?2???S???????n-?_?O?K P?? ????}?Un4?;i`??n???@?(8s X G-???,?????D??Q?^4T?8??_N-???:(??IW?g?#?????,?C?@lE??z ?x?>R? 7'!????????)???j?M?????8??E?yS??[???eI L1$($?r?????? V??y??&??&|?5]?6?????t????p? ??8? +?D?`??s:?nw??:]n??H?? ?i?endstream +endobj +170 0 obj << +/Type /Page +/Contents 174 0 R +/Resources 173 0 R +/MediaBox [0 0 595.2757 841.8898] +/Parent 181 0 R +>> endobj +171 0 obj << +/Type /XObject +/Subtype /Image +/Width 149 +/Height 110 +/BitsPerComponent 8 +/ColorSpace [/Indexed /DeviceRGB 63 182 0 R] +/Length 1649 +/Filter /FlateDecode +>> +stream +x???m[?:???BjmjZ????e???v?]Q????Ih??$!Dv?s]<~??-7O??????S???????Oi?}?tjru???uTE?L??~?s ?@?_?"T??????? ?r?????]??V? 0?7$??,????B??^??>a???s/???T??!D1?J???+5@ ? +??B?????Zu&k?*T?????A?????@Q?X?'f????Q??5("B??RV?{|???|?P?y*s~????a?X7&In?3TO??kJ#Ty??l??s?G? (Ju?k???GTP?f[?????4?tD?UZ?a#?LFi?Z??s!R-???&F??;5V?? ????`U??0?m+P%?*Q2lQuP??%??)f6n? +s????1D ??|z|J?????U??aYN?5?T?R?[APSh?Q????#J *??1?P?r?*F)A???:??J?(%??A (?C?b??5???B?????Rs*?? ?TPa????lT)%?6c?(?? (?n-?A??{????#??w????'42jI?d??oL??q?!75J8i?6?x??Y?F?????s4?"wt????????MZHt??{????(?L?????d??a??? ???ne8?:3HL ?D?G|*?M??????I??wW;??0?#???!8"?????R????+?Q%6*u?r??h? ???T?*0By? +? ?t)1??=7?????;???t'w*T????\VuRe?sV??L??&????KJ]??,??2#q$?8?????Uo??P}????b{???d6??w4T=?o??%_(??,???$?zX???R\???2?J????&?H?>??N?#?1}?$??2?e? ???FoH?Q{=??#V??f??????7 ?????+?Pd ????L????]?????????l??F?t?{ xD;`?J?T???m???M?????} ? u???|??bqw????.Z???|?;?gyY?d??????77?????e&8?Q,?:?e???^?\?A%ow?2??c?1??? j??N.&~>??=?t?a~6?"?????4???j??????w@?U?????:??@?YJ?? +5s=??0??5&PVE?f?|&???????|*?m??Q???????????????????????;E?ZEz?)?~?n&"F????r?W????g?:2(A ??^ad=?tx??????????W?endstream +endobj +182 0 obj << +/Length 203 +/Filter /FlateDecode +>> +stream +x?????/?&T??:??^???????k????????????pK???????S&?Z????D?????-???????????????|?? +???_7??O??-???ph??wWO????b:?h ???????????}?|???????????u*????????{??????{Y?????x??,??s?4??????(u[endstream +endobj +172 0 obj << +/Type /XObject +/Subtype /Form +/FormType 1 +/PTEX.FileName (../img/ist-norm.pdf) +/PTEX.PageNumber 1 +/PTEX.InfoDict 183 0 R +/Matrix [1.00000000 0.00000000 0.00000000 1.00000000 0.00000000 0.00000000] +/BBox [0.00000000 0.00000000 385.00000000 199.00000000] +/Resources << +/ProcSet [ /PDF ] +/ExtGState << +/R4 184 0 R +>>>> +/Length 185 0 R +/Filter /FlateDecode +>> +stream +x?u}[?%?????&?????aO??{l???????2W?66????zS_???_??? +?????????????????????????}??u????????(?u|???????/+?o?(???????R??R?)??????????j?w???(???????s??fF5???&)g?+??????1??3v&^?'G??YX/?????/??_????>???n>G????^z|?u?B?a???h p|?????|?%??!?? +?g???,`?>?O??c?????~??[]?c| ?????7?t????)/?????k?? ????y3???q???????T?4??]????zO????fl?l?*???o ^??n?]??#???Qvh.???KOM [??N??>?i?z???????M??d<]j?s????k??????"m??j??^k?<.|????~? v?p??kn??E?s???-? +?n??g?~??^x???w?]p??X?~Xvj????????????4q?p~???8 +??|G?}j????c?pw>%?%?iR????l?g_????,!?????????O??V?7????Q?[??"_,?????????!?/??,BS?zL=?5_??t?P?1???5?.???g???>cN??b??)Z???x???kK?????l?Gw??!? ?3?]??#??s??????&?4??+{??x???Eo??w?S?dw?y?@????(;L??F?U?{D????|?)??H ?t86^???????*Y?h?NN??????VN{#W??OM+2???a?????:???????z?{?Ys?_???l?X#??\?0?$???B?h????D???~nIx4??/?h?E??? %????}?????? ?gR??` nI?3?$??l?? zK{(O???? ?Q???????g0?????(lI9?%???s?~OH???y??????NHn?a?????????Hc<~?????8??s?xU?VJ?jS?l?X]s%/????K}??????bs??????Au}?lnh????????m'{??u???~:kS??n<[??*?g?]???fj?????????w????????????????-??I??[???? ??.C? >?{??X?????sk*??J???A???E??1??P???????9n???jT$???:?? g??<]/??"???IQ???8?}??!?|????-v'?,a +rC? ?8?????+??T?? ?????3P>??y(?paKIB]???tThWV??7?n???B?\?R?$??,??sv??|?n????Y,?* +????V???-???????_??s%?a?}???? U?'??zA9H#??C8y? ??$P$??????bI????t??d??.??? +?/?_ ?(2?B?w?'??????^C?N????S?????c?:`????z_?????\(8!?Q??X_?sP?^wm??????\?e????bS'aK???C???h?p?$?.8?^?aj?J\-_???????4j????}}????????&?&!?L??\?=_???By??? ???o4?,?z???5????i???jnM ?dsA???!??\.?~!C????&????&|??4?;.?`???G?^???X=???X????R????}y:[???j?/?Z??H???/L{1 ????X??k?Z?V???t??'3???Ax???B?,? G??N? ???????;?????F? ??re$a?8????O8?}K-?l??Y?????8/??9?9x?#???D?6[?.Xc8??????????Jp???@8?5;??M??N????????{??R(??M?G?????Lf???"/Be???0??-??A????|?GK?8?CI???+???X?q?r?+ ??T(LX?? ??!?&V?????v?????s?P?j?Q??L?L??st?????u???3?s????%????F???? ???tA??#3??W8??0??G???? ?=-????t???2?mI8NJ??l)?? +M?y?*Q?BB??L,?? ?=??/?????)_?????6?:O? ??yDn???!4???????{???vyl?????????/`?Uzf? +? j_M?-:??f?}?????????????{??4??K4V??????s??dK????v_Wg?"????-&??|???!?`f???????v????`???2??? +??]???m.A??U?VM???????i????? ????%????q.d?????????l???????ms R?????m/??B?6 ?'??????? ?H???v?f?J?>????C???C6 ????6 ?z??V???d? ?"?>??'?????:5??88S?? 7?????A?? ?jO#`K?z???w??G??????b????W?u>2??g?X??*???d?3?'S?P??[??????6t??(j?|???lp)=O?K2Gru??w???(?hR ????????W???K?g?Q???/?j?????E??I????rf?sN??a1??x??H?7?'=V??* ?????+!?I ?B??f`?Tnl??z?|????$<N$E?????G\?B??K?z?????G?M???R?RS???%??\?S?}?? ???N???EdA?.?? +?`?Eh?4????&A?tx?"`????r_WNVo?[?S ?p???!?z?0-?K???O??~??S??;??? ?&N? 9?XC????S? ???j~A$??????? ??V?Lg? ?Y?1?5?n?Oj????et(? Z?7W?@ _?>? +?????????????HVD????b???????????^mz -f?!mE@?b| ?8?@?t!?%?????????SU????(\?K???>?to?E?*+? Y +M??D??0?????:?WD?C%??@7;? + g??I?????m??*H!????X'C???{????ib??????RKE????X?B W? G;k?O ?{?B%?R??}??:?v???B8?q???q'???PYtY9?Dn$l&?x??*????????x??dBD at .??j??S? +??5??6Fg?&???????8????????/, ?????6?T?4i?L?v?????U>/h??????G +pW?4?{2???9????B?t????U?????? ??`?qc???JP??~~A+??k ???????l,??2??O?? ??_8/????v&??? 8=?O?\:???.6??Q??n?H$?v?%{ %???i?8??&???3??7????????q??T????8???D#??t[iai?X??b?.:]????????1??.?E?*$ ??\*{?L??W?#????] ????+J4h(???Fs??N??}B]??? ????n [?H?????(?I!??)??S?e?????????w????|C?>R?7d#;?????./?q?b?R;O???!?|.?? ???c???? +?v F??5A???O?P????? ? ????\`}?%*?$????9Z'bQ:???o?Q???CQ?a?A9?{o@????l ??=,???K@????j?,?F']?Lx+???&6?S???[Th?`?????????d.?3>??f???b@??%C?????%F?h?/pV5?@% +?X%[? ?X?x??d?2_Hp?"> ]aX.0S?Z???6???????? L?F?'?o@?U?>??`????H?9?l????U?q???:??f?????/?????@??#=?e?lG7i"? ,?>5?`?|\?%?5sm??5??1P??O?j!F?W?W???????`7?????s??OHY?:?c|Kb2??@ ??m?*Pq??z?!4^??? 9?????/?zrt?T????A6??C?Le%???UJ:h?? ???`2?? +??x?s&?Y?d)Y ??A6:??EKy?8???V@F]?Pg??7??????F????@???$?2?? l???c!e????uF\?????aM?R????<T?%?p?`??F??jh?`I??m?kD?c?+?#? ?1??K??????MtW???it?n?v??=? ^?Q?J???z}????8??M?j??:?;6?2????CHS?8?7li~?1??P?5?o?u?m?I'?!?fIE??????????????k-???#???M?????????? J;B?d?r:5$Lf?$3???n?B+gL6??z?0[??(?a??? ?O??????????/=? +ppk??S?O?(0?0?U?"???]??6F???????2?????XQ? ?^%?]2Rxz??]?S????pe?p?x!k???M??w/?B?!??2?vD??(?}+ ?v?R?)$p?S%?D[?LDf???Q8?x?E)????d??7???F?@??????????F??????2 ?UB??????l +?R?>????/?Pxb"?l??=J??5%???O=(??2?.R?I||A?*RN?o???? e???v???S??????9Z?xg??23?$8???X??M?`??????I?F?? ?4???Pn??????-x8?Z$7b5q???Lp?Hx~?r(???]?d?w?+#??ad??:Fx?XIZ?(f?????OW???9d|}??????????|N???~????O N?? ?j=?=??km]??PI8????k???~H8S$al1? I???????C~?K???fH????^???/h>?7@??br?S?I +?c??B??!)????]X??????????T??+&???? Sk-B???CPn"??9#??_?gpX ?\~??f????0????????E?`?g???a ??????o???Q??7???dr|?{2 ?V?!i?????u!}T?/????S ?N/?J?I?Syl?K???C{ ?Q????]?? +???J|?jFg??~??~?3t???HY4?k;??]z???H?D8&V?`93?J.e?#&;??????????<,??qF?rR??P????? m/??[?"?OH?%?KA??;?6.;? ??U?????c?sw?.????`}?hQ?D??}????????????8??a????4x4??y??N??U?A ?.?fFeF??=x> ???%`9N??G7??S?N??`*$????N???Om??W????r$??T{?o-?D??c??a????)F +BFt?1~d?? ?3a????f5/?p????2y7?>1??< ??#????_????????_?Y???2????X??[i??8? ? F??????.??,@^??b:?Mz)????e?'6?HGz@??t????9c???a&??v?~?v?:??H???bFc^;??+"??}???UO????g???7?I?.sP?vZ????M*:??????0???x:C???:J??vB???]??T)hjE?9n?v?:P8?em?? $G??'???bxD S?????!?{@Y??j???I ???*c??2Y??&d]%?C?4??D???.???}0?UqB?;?y?/??+???Vx?? ?d^O??]?w?Hyin?O????b?/????8?#Q?k?j9??U?`X????qwd?????>?`pB?W?>??F??W?>S??? X?d? r?7?+?L??????B-rm??E??????|?H+Y#E^Eq?L?=?? ?\A*D<)?,????5????(???L)?a+???*X?j?????? ?????????a[????,b????? ?u#X???G??? =??N???f/??%?&~ *?????.????qR???H /?N??Lb{p??????u?G^??????Q?$?i???1.??iD0a?????(E?2?b,1b?QBh>???V??????]0?H??-?|?@o???_|f?A\j?yb???????$?u ??^?pv;/??V ??rb?O??{3gB=?5????,???????Dh???#?qK?H?Gm?Rc?K????:?????&2?????h?E? ??f?????+7???????????d??$?",?9???[x??X?70?G?"??????>FZ??i?I???|c?Wt|}?-3??9?????K??$0xU:????u!?? S?????-P?3?.B?E?,]?Dj?.???j=?G?d???w?x`???y??Q??????]?? ?q??b?????e????b??H^p?T?%(9???r!?C????n6?d??3$p?K?`H??5??Z??~4????`~L??\???z?i|??(???-{??f5?q ???_??K #???????????Y???=O???4 +]5U???????}Mj??+?s39~???? +^y ???/e?? ???sF??%????b?1?*?&??0?? +???d????~M?\|H???_D?s^y??p?a?o??H?)???}????TtR_????Vf?#'?a??R?fC?p????b?-??6Am???*?????0??q???N??d???o? ?Y?_??>??C????N??`?%?> +endobj +184 0 obj +<< +/Type /ExtGState +/Name /R4 +/TR /Identity +/OPM 1 +/SM 0.02 +>> +endobj +185 0 obj +10833 +endobj +175 0 obj << +/D [170 0 R /XYZ 74.4095 753.1919 null] +>> endobj +176 0 obj << +/D [170 0 R /XYZ 74.4095 735.2591 null] +>> endobj +177 0 obj << +/D [170 0 R /XYZ 74.4095 735.2591 null] +>> endobj +173 0 obj << +/Font << /F26 180 0 R >> +/XObject << /Im1 171 0 R /Im2 172 0 R >> +/ProcSet [ /PDF /Text /ImageC /ImageI ] +>> endobj +188 0 obj << +/Length 2299 +/Filter /FlateDecode +>> +stream +x??ZK?????W??j????sZ{?q\???z*9?>PGb?"e??z???P??yH?f?D6????4@Q?cQ"????%?X?v3m???3?t??"???i????DH????(?D? 4?3????????????4~K???/?L??y????9? [???C^UEU??WV?44>?u[???????m??v_??v???w?? e$?@?h??d???9?'I?G%ax??)??I????~?(?0f?h??P?????Vg?????Eo?????{o?HR?q&???0?c???3??`?w3??,U?g??G????H??^R?~??6O? ?????E?)I5D???|?k%\?L~,0,-?S?}[?]??4~9?_??%t?? +H??lh??V??P?&[?B[???1l?s_??z??T?H?????q???+._f?k?FAs???q? ??%?????. r !A?????q?T at k??R???N8Q??v1?Is?????Z?,?G????~???O??F?;?Vk?????????mLfL@?Qc<Bc~??[?mga??_x??r?.???lY?G?}W??/9n??l???????fT???J ? ????%hu2??"?t ?NC??? ?2j??Kh?99???X_?d?v?????3??e?)?`??~|e6?E??I??4?4???P`???+4*~+V?????=?,?nd????y??????}?",M??>?6}|???g ?'Ot??f*SN???)???.????e5n[?????%K??c??T6=43??)u/???????? ?oR#lu*n?#??????e:????= B??;Ei?|?Y???h[+?,k??rcf??"?t??6[RN2??I?U???t??3???m??N??Q?'? ????"/?B??q?^?'?d???b>?e?9 ??gUy??????v}r??~?l:??:???;??J8aj????T??d,??Y??^]1?6??D??6)&3! ?? ????? ??~Q??;?yr/????y??????+W6?Y?j{JE?H#???????????N2?XJE??3>v??:{F?z??P?&3"??????xtU?U????o???6&???I??@ +"U???#Y>?V'#?(RO??$??t?D5?!4f???E~?G?'~?E?????????????a????;_?(???????e??Uw????$?a? +J??V?i[B(2yv?he??p???m??.?bW??MM!&??{?d????i????FX?g????P?F???W???"?6v&?=?h??l???;????|'????S?w:Xh????/??U:%?Uo +???T??c?=(???????-(T?k0????%???"???> endobj +193 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [100.0827 750.9806 113.1137 766.9208] +/Subtype /Link +/A << /S /GoTo /D (page.47) >> +>> endobj +189 0 obj << +/D [187 0 R /XYZ 74.4095 753.1919 null] +>> endobj +194 0 obj << +/D [187 0 R /XYZ 74.4095 709.6344 null] +>> endobj +195 0 obj << +/D [187 0 R /XYZ 74.4095 697.6792 null] +>> endobj +196 0 obj << +/D [187 0 R /XYZ 74.4095 493.6483 null] +>> endobj +186 0 obj << +/Font << /F26 180 0 R /F31 192 0 R >> +/XObject << /Im1 171 0 R >> +/ProcSet [ /PDF /Text /ImageC /ImageI ] +>> endobj +200 0 obj << +/Length 2852 +/Filter /FlateDecode +>> +stream +x???YoG???)???v?G????5V?e?C??K?y("???????a??L5M ?X?gWu??????T??G*??FT?i????|u??+???4?Qt??~?8y????p??????Jc????J?!????'?????S???V??<=e\M??????)????y??>??-??r?]??_??2{?He?????N C?+??3?Wj???HO^^??"? ?L??@B2?{??s{$??D?i?w1?X?Zm|?*3N("D???^?[U?h?Zc?'????^}?o?_D??)??? 1??mG"?5o?UUq??q?J???uB??'8?????T/6'??T??{??F?f?e??q???O\]???zb?1ZT?m?D??lu??D\H_Y????????>:DA1??Z?? +???P{|?6?]??????bi;% -???D=???6?dzj8???? ????3h???V3??Z?}???]3?t]?E?g?D????hLF?HypP=??jlS?7????????n?rC??f-I??~????> +?+???1?x%????B??4??cyPm?4?u?:??U_?aHr?u?{?v??????S?V'3?d???:?;n???w?,rG=wP?>??n????????rf??M?????@ ??{.]?s??????`?4Uj?*5o??O?Q2A??gD??????Q?d?L[*??nn???L????/??Y.??]?U????zqs?t?x^2?7?S??20? +}`#?E?????AHP??VB ???$( ?T?jQQ?57?????V???M? #?W?? ?b?$???2??q?}??[?w??z`??d8?R#?~l\?#%h???=??+?W0?ykW9?+d?????)? ?k+?????????????w??6???l???y?? ??*5=?K???a?e???&Q0?{*?h??9*???@??'??$C5>???HeX??v?3??Q??P???Ijc ?U???D;?<%?p???? +F?o??:??Z}@??aJ???,??????_???f?=?pe?3?V??? WAU???p????^?j??b?? ?6o??9?Z}@:ei?J5i+?|?Q>???? ?1,y?Z@3? +???L{B?m?&??5w?i|??????|@?b?eM?\?l?3wy??b????????Aa?????hP??!??????#??G?"? +F:o?J???> w? +3R,E?,??[? fT??(???3???????O?>_????E???wO?y????.??H??K?w;????+?8W]??IXGi?????!o????i??>?6[?K,KGh?,?????p?6??J??????????`^?6v????Z;uw\{????B?NP#???P?????g?c3 /?k?`PL?????0?????Hc]*.?*BV?????-?g??????/?v?3?_6??**??z?????i.y????f????/??7^PB???v;k??5~\?????_????D???[???T'iendstream +endobj +199 0 obj << +/Type /Page +/Contents 200 0 R +/Resources 198 0 R +/MediaBox [0 0 595.2757 841.8898] +/Parent 181 0 R +/Annots [ 202 0 R 204 0 R 205 0 R 206 0 R 207 0 R 208 0 R 209 0 R 210 0 R 211 0 R 212 0 R 213 0 R 214 0 R 215 0 R 216 0 R 217 0 R 218 0 R 219 0 R 220 0 R 221 0 R 222 0 R 223 0 R 224 0 R 225 0 R 226 0 R 227 0 R 228 0 R 229 0 R 230 0 R 231 0 R 232 0 R 233 0 R 234 0 R 235 0 R ] +>> endobj +202 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [100.0827 750.9806 113.1137 766.9208] +/Subtype /Link +/A << /S /GoTo /D (page.47) >> +>> endobj +204 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [73.4132 675.6979 185.3922 687.2594] +/Subtype /Link +/A << /S /GoTo /D (section.1) >> +>> endobj +205 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [73.4132 649.5908 148.1823 659.3641] +/Subtype /Link +/A << /S /GoTo /D (section.2) >> +>> endobj +206 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [88.3572 629.9396 237.0378 641.2171] +/Subtype /Link +/A << /S /GoTo /D (subsection.2.1) >> +>> endobj +207 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [88.3572 612.0068 229.4267 623.2844] +/Subtype /Link +/A << /S /GoTo /D (subsection.2.2) >> +>> endobj +208 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [88.3572 595.8175 209.6015 605.3516] +/Subtype /Link +/A << /S /GoTo /D (subsection.2.3) >> +>> endobj +209 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [73.4132 567.8972 177.8803 577.6704] +/Subtype /Link +/A << /S /GoTo /D (section.3) >> +>> endobj +210 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [88.3572 548.0267 368.4335 559.5235] +/Subtype /Link +/A << /S /GoTo /D (subsection.3.1) >> +>> endobj +211 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [88.3572 532.0566 248.1661 541.5907] +/Subtype /Link +/A << /S /GoTo /D (subsection.3.2) >> +>> endobj +212 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [111.2713 512.1612 285.8751 523.658] +/Subtype /Link +/A << /S /GoTo /D (subsubsection.3.2.1) >> +>> endobj +213 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [111.2713 496.1911 242.3489 505.7252] +/Subtype /Link +/A << /S /GoTo /D (subsubsection.3.2.2) >> +>> endobj +214 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [111.2713 476.5149 336.3948 487.7925] +/Subtype /Link +/A << /S /GoTo /D (subsubsection.3.2.3) >> +>> endobj +215 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [111.2713 460.3256 213.3077 469.8597] +/Subtype /Link +/A << /S /GoTo /D (subsubsection.3.2.4) >> +>> endobj +216 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [111.2713 440.6494 245.5764 451.927] +/Subtype /Link +/A << /S /GoTo /D (subsubsection.3.2.5) >> +>> endobj +217 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [88.3572 422.7166 243.2551 433.9942] +/Subtype /Link +/A << /S /GoTo /D (subsection.3.3) >> +>> endobj +218 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [111.2713 406.5273 196.9393 416.0615] +/Subtype /Link +/A << /S /GoTo /D (subsubsection.3.3.1) >> +>> endobj +219 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [111.2713 388.5946 250.5676 398.1287] +/Subtype /Link +/A << /S /GoTo /D (subsubsection.3.3.2) >> +>> endobj +220 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [111.2713 370.6618 191.5299 380.196] +/Subtype /Link +/A << /S /GoTo /D (subsubsection.3.3.3) >> +>> endobj +221 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [111.2713 350.7664 231.7885 362.2632] +/Subtype /Link +/A << /S /GoTo /D (subsubsection.3.3.4) >> +>> endobj +222 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [111.2713 332.8337 233.3027 344.3305] +/Subtype /Link +/A << /S /GoTo /D (subsubsection.3.3.5) >> +>> endobj +223 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [111.2713 315.1201 214.7921 326.3977] +/Subtype /Link +/A << /S /GoTo /D (subsubsection.3.3.6) >> +>> endobj +224 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [111.2713 298.9308 333.1668 308.465] +/Subtype /Link +/A << /S /GoTo /D (subsubsection.3.3.7) >> +>> endobj +225 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [88.3572 280.9981 284.4894 290.5322] +/Subtype /Link +/A << /S /GoTo /D (subsection.3.4) >> +>> endobj +226 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [88.3572 263.0653 177.8509 272.5995] +/Subtype /Link +/A << /S /GoTo /D (subsection.3.5) >> +>> endobj +227 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [73.4132 233.023 289.4509 244.9182] +/Subtype /Link +/A << /S /GoTo /D (section.4) >> +>> endobj +228 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [88.3572 215.4937 178.2991 226.7713] +/Subtype /Link +/A << /S /GoTo /D (subsection.4.1) >> +>> endobj +229 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [111.2713 197.3418 222.4536 208.8386] +/Subtype /Link +/A << /S /GoTo /D (subsubsection.4.1.1) >> +>> endobj +230 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [111.2713 181.3717 222.9319 190.9058] +/Subtype /Link +/A << /S /GoTo /D (subsubsection.4.1.2) >> +>> endobj +231 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [111.2713 161.6955 324.669 172.9731] +/Subtype /Link +/A << /S /GoTo /D (subsubsection.4.1.3) >> +>> endobj +232 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [111.2713 143.5435 218.9866 155.0403] +/Subtype /Link +/A << /S /GoTo /D (subsubsection.4.1.4) >> +>> endobj +233 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [88.3572 125.6108 223.5591 137.1076] +/Subtype /Link +/A << /S /GoTo /D (subsection.4.2) >> +>> endobj +234 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [111.2713 109.6407 239.0905 119.1748] +/Subtype /Link +/A << /S /GoTo /D (subsubsection.4.2.1) >> +>> endobj +235 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [111.2713 89.7453 340.3498 101.242] +/Subtype /Link +/A << /S /GoTo /D (subsubsection.4.2.2) >> +>> endobj +201 0 obj << +/D [199 0 R /XYZ 74.4095 738.0292 null] +>> endobj +203 0 obj << +/D [199 0 R /XYZ 74.4095 696.3583 null] +>> endobj +198 0 obj << +/Font << /F26 180 0 R /F31 192 0 R >> +/XObject << /Im1 171 0 R >> +/ProcSet [ /PDF /Text /ImageC /ImageI ] +>> endobj +238 0 obj << +/Length 1197 +/Filter /FlateDecode +>> +stream +x??X?n?8??+?H@??????L?)P m ????q???Z?n???+R?i??<`?? ??????G?????EZ`A?D?L?eh??z?{?m0???????? S? +??bh?@?`n4L?,????????????0C?k?1}YL????YU-?????yW_?v???\-?? ?:-8?w?M???????????R??U?i????Sd?U? $A??rl??.????vQC?_?mU?PL?EZJ,??????????8?I?w?D???r????aJ??D???????f?????_??r}_??/*?aF??f%$???(??u8?,`??C??p?kF???S?~]St???e???? ??r??b*a}???????@=?H?T/?d???PXH???*??????G??(?????ll?c d2?k?S??&??Z?[j?0/&???}?p??"/7????z{?????.?L?jMw??5???Y?I?;D???OX????*???i?&?E?????&??^n?6 +,1??K????\?Ke???YTP????~n?x?:rS?kw ?a?, ?6?bZ???????9?^???????????Dp o??E?xhA???o"Z???? sHg?B?2K????? ?,??1}????3e???,?LvT?v?hc??|xr?X~ ??n???|?fh?N8Q}3 ??l9?dn?>???3?A??8?D?????[Q2,?T???m???\?1?X??????wQ???L?vn????;??1??IcZbb$Gqr}5?H @2?~l???5J4E\$?$q???$??*8?3 +(?Bk4s?a+?? $?#X?????T??p5??Mc??jPsT+l?P(?? ?HV?H?4??i?????jS??8????F???SQ?#?????,?`s*??Y??d???:???????q^??W???.v?+8?G?Eq??rj$??,M =MD?n???4? (???>?A?????v???zk???????2q? ?????g???U?????i???@?L[??T??? ?$??J[v????a?kQ?'L???????f9????ur????? D?N?]~j$G?-?%??&??1?!?Kr{??4????????d????? b-?i at y?2/????k??M?V?j?N?`qy^??(!?p?P????I???YX??$???tJ?)?#?&y????+????z???:?L???\?w?/_??endstream +endobj +237 0 obj << +/Type /Page +/Contents 238 0 R +/Resources 236 0 R +/MediaBox [0 0 595.2757 841.8898] +/Parent 181 0 R +/Annots [ 240 0 R 241 0 R 242 0 R 243 0 R 244 0 R 245 0 R 246 0 R 247 0 R 248 0 R 249 0 R ] +>> endobj +240 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [100.0827 750.9806 113.1137 766.9208] +/Subtype /Link +/A << /S /GoTo /D (page.47) >> +>> endobj +241 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [111.2713 707.0703 243.1758 718.5671] +/Subtype /Link +/A << /S /GoTo /D (subsubsection.4.2.3) >> +>> endobj +242 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [111.2713 689.1376 358.8599 700.6344] +/Subtype /Link +/A << /S /GoTo /D (subsubsection.4.2.4) >> +>> endobj +243 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [111.2713 671.424 295.16 682.7016] +/Subtype /Link +/A << /S /GoTo /D (subsubsection.4.2.5) >> +>> endobj +244 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [111.2713 655.2347 276.0815 664.7689] +/Subtype /Link +/A << /S /GoTo /D (subsubsection.4.2.6) >> +>> endobj +245 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [88.3572 637.302 177.8509 646.8361] +/Subtype /Link +/A << /S /GoTo /D (subsection.4.3) >> +>> endobj +246 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [73.4132 609.3817 144.1971 619.1549] +/Subtype /Link +/A << /S /GoTo /D (section.5) >> +>> endobj +247 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [73.4132 579.6979 213.496 591.2595] +/Subtype /Link +/A << /S /GoTo /D (section.6) >> +>> endobj +248 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [88.3572 563.5784 231.2003 573.1126] +/Subtype /Link +/A << /S /GoTo /D (subsection.6.1) >> +>> endobj +249 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [88.3572 543.9022 201.0335 555.1798] +/Subtype /Link +/A << /S /GoTo /D (subsection.6.2) >> +>> endobj +239 0 obj << +/D [237 0 R /XYZ 74.4095 738.0292 null] +>> endobj +236 0 obj << +/Font << /F26 180 0 R /F31 192 0 R >> +/XObject << /Im1 171 0 R >> +/ProcSet [ /PDF /Text /ImageC /ImageI ] +>> endobj +252 0 obj << +/Length 3597 +/Filter /FlateDecode +>> +stream +x?????6?>_?[?*?! ??=e???S???g?C?EqF?)RI?'_?? >F?-?@???/??x??7?v????X%???&??x???????A??X?????? ???U: +6w???sU??Q???c???wO???? ???^???mwJ????m?/??s +??vv????????G???s.Y?V?v:]?? ??=y?n???????I?4b?o?????8??C??c??G????S???zq???? #??ry?? ???'Lv_??4?x???????3?X/m?X w}?']??i_\???2x^4?J??U?K`????D?v??6??Af???6@???u??}? ~???o^77??l~O???M_??R?A>4???????? hO???G????f??#W?QlF??7?????11 <7?@A_???*x)?0a??? y?s~?J????Dk???S??????? +E?p??????%H#?k?j????~)??????* ?|/tG?2t???RX???E?C???}?wO?????~????@??????P?X??????"_lB??`??!???_*?bU??k/t????G??????5H?w]????!l??l?^?x??4 ?N^?j}?B?{:?9??'J??A?C6??'?????N1????$_??/) we?W??C4???G??J????R??t9a?]R?????p???*n W +g??Uq*?.C?E;?Ff%??d?????@?????&??^??6???g??k??%?/ i????+???ymq???p{??!?*??cam?Fop?F??~'?V?mO??T??Q# +???Sc,,???v??;??? +??~?????? "?P??;?i??u??h)k?????+zG? DXj?H?#i3? ?k??k??^????????`??Xl}!??Q?D#??????fj??'|?<% "?.t??q?4??E??&?lZ^D?6??^0?????z?vJ2=?5??S??????VY?b??s???j4?8????bLY?&,????5???}T]?? G??.?Z3n???R??]VVd ?8v" ??m?Y??|??rF??}v$???Y???l?Rb???Bn??IV%3?L?? s?&b????g??? +????{J???????3?:???P;?P??`|PvRc?????;f-?? ZZd?t??#????{F????S +V)c??.L?5Ke??i? + ???zm{?8?)e@?????????*XET?a8H>?????r??%??I????V5?OUm=?@f??xY??x ??????Mr????*?ij2????I(? ???????+Rp?Nv??=??]?u at c? ?l?????2?0???|?4te????o?4?3Q?=?(?dx 9?Fmb/B?u=??se +1 M]??A???????4?$D`=??z?Ac ????r$?oh}hy??h?H[?,1? 8???pv????r??v???h3?V?L??~U?????06 H?aA_8??R){?J8'?dM????w?Sr???3?? Q??9%s??X??(?e ??n^!2%;?n?????k?*D??*DI??P?q-$???/j??v!OO?n??4?WC??S?????&?+?6!?C'?V ????#C!d^tNBWE????????!U?q%-?\OGX? ?T{????? ?PWF?????????g?????5q>??b????%???a"?4??cqGo???uO&`???@???C?? ys???0??0?E?}?XPP? r??rsf??6 ??v?9 6q ?j?Mi?????&?ec?W5?i?w?\??F??3}?? ?YW????N?S?*?N??|S?F??????Me??!}??&Ug????F???d???22???????ic=?OX/???6???i?????_?X??Mk????7??????4,???????(]?f%????a??,??VG?d{??Z1gw?$??????@W??@Y?O?n??????U?/W{??A?,???5{y??^?E????fi???.?n +?R?:??K+?YG ??Ir???XW?????????h??;????0?2IO?NJ??`?o_??):?{Y???,???S???:H "???O?P?????:?8I??I??:I q???w???%??sS?? ,O??n?2`?j??vF???&??3?:r?`??_?m?????endstream +endobj +251 0 obj << +/Type /Page +/Contents 252 0 R +/Resources 250 0 R +/MediaBox [0 0 595.2757 841.8898] +/Parent 181 0 R +/Annots [ 254 0 R 256 0 R 260 0 R 261 0 R ] +>> endobj +254 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [100.0827 750.9806 113.1137 766.9208] +/Subtype /Link +/A << /S /GoTo /D (page.47) >> +>> endobj +256 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[0 1 0] +/Rect [472.7408 677.5112 501.4627 687.0453] +/Subtype /Link +/A << /S /GoTo /D (cite.D05.1) >> +>> endobj +260 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [98.3198 370.6618 186.3587 380.196] +/Subtype /Link +/A << /S /GoTo /D (stackless-features) >> +>> endobj +261 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [98.3198 145.536 300.8681 157.0328] +/Subtype /Link +/A << /S /GoTo /D (optimizations-and-memory-management) >> +>> endobj +253 0 obj << +/D [251 0 R /XYZ 74.4095 738.0292 null] +>> endobj +255 0 obj << +/D [251 0 R /XYZ 74.4095 720.0964 null] +>> endobj +6 0 obj << +/D [251 0 R /XYZ 74.4095 720.0964 null] +>> endobj +250 0 obj << +/Font << /F26 180 0 R /F31 192 0 R /F14 259 0 R >> +/XObject << /Im1 171 0 R >> +/ProcSet [ /PDF /Text /ImageC /ImageI ] +>> endobj +267 0 obj << +/Length 2035 +/Filter /FlateDecode +>> +stream +x??XK??6??W?(?"?z??v?.Z @?.?C??,km?z8+)???;/???&E?53??&???k???????6 +??Z??????XC'Tlr(\7?~?#??&Y??#?a?????|tmS?+??W??|???W??u?89g??\%?(??`?????????\?lN|?8?{L?x?rd?RTx?3??????c?i6???>@3??w??m?????gZ??m?k???b????????????q??,X?????????! B??? ??F????7 ????D????????B??\??|?)*d??z?~"&?I;1??`I???s?K!m-?D0bU?xj?Z??eU?-J??g?m?=??????v????>W?(70?*???-wC ?M?n?@Zsok?!?b?Y?i )??Ed??hdq$???y%?w?o?0???????;??f?G;??,??.?????,m??S?z>?(???p??J+?9 ??q%7m???????l`#???fy ???? ]?Y})X`?????iT%??5I???%&#\???5O???T?? ?mY?.hd????=??d@??????????u??9?@d??Fv [?f9?-2]G???~???'6C???|5?E ?\?o?x?9?8Z??l?^??6r??????br? .??????(??9?? +???4?&???=(????R???????;nm?r??dn??D?^?v??Ws????;^???s????Vg??)?'j??zw??????XMK.?\??p???r??E~?????$?|qW??r`E???K? 6??"?H??,????p0????o???_$w?b??y????A??????w?d?5?w????9v??B???g?????o?pcJ??????????lAendstream +endobj +266 0 obj << +/Type /Page +/Contents 267 0 R +/Resources 265 0 R +/MediaBox [0 0 595.2757 841.8898] +/Parent 181 0 R +/Annots [ 269 0 R 270 0 R ] +>> endobj +269 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [100.0827 750.9806 113.1137 766.9208] +/Subtype /Link +/A << /S /GoTo /D (page.47) >> +>> endobj +270 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[0 1 0] +/Rect [250.5367 440.0417 276.778 449.5758] +/Subtype /Link +/A << /S /GoTo /D (cite.VMC) >> +>> endobj +268 0 obj << +/D [266 0 R /XYZ 74.4095 738.0292 null] +>> endobj +265 0 obj << +/Font << /F26 180 0 R /F31 192 0 R >> +/XObject << /Im1 171 0 R >> +/ProcSet [ /PDF /Text /ImageC /ImageI ] +>> endobj +274 0 obj << +/Length 1734 +/Filter /FlateDecode +>> +stream +x??X???6 ?_??9@?J????u?uk??????>???G;?n?HQrl?? ?.I??#EYx??+?x??X&??i????{[???V&pB?X??????a? ???B???K8?I J??i!?????>?>??0?? ??x????wY????!? b??8;dUUTeW?#??Zr??5]????e??e?/??[?{???^???'??R??| ?q??(???n?????8?b??????#???"F1p??X??`b?L+???3?"dB?jf}?A???3mh????????8?LhK9??^)-??<=??D?9?????3SFj<???P)-?????w?????????8ai($?+eB??????po{?????~?10????RS:??Z}\?t??f?Ru?Y@??wH??&?p '?????k??vs? + ?P?`???E? ??T?R&???#F?????h8??~Wv69??XM???0b??Gw??p?????r2S???????E?bb???Z?!?????x??)?"??X???P? +??e????B?D,?????? unw? !??2??????? +R?????QQ?????a +???_?d<????U~????Lh\?????)6??l?????EC:?X??Ls?W????]??d??*?y??-?#?-?l??sy?)?d+w????????ds???d?X?8,?a????}?w?h??f??j??????????5dY??????pP??b?N??xK]?? v????xfw??w.f??/k??n????(??ZE? >D<???/?]S?Y??????G KD_ ?H?R????_2; +???!?R>???)??p7??Z??-???p?m "?-????0k????5?C??x!/?Ly?#{?|rz?RH?Z,U?-???|Z?{????:???3T ?*???#)??9?-OJ&q at 1?v?\???(?`? ??-]?\?I??,??b?Ow?~??X???S?? k???4???I??l??q?????*?q??????? g)Q???????R???Dve?[J P?W? ???I?]??P]?@3G????? ?n]4?h??T .?1n!?? ?????hf?&"%??$ u4?;';?*???5}???_?=s??"???L?=???u +P ???DE?6?9Xs-???:Y?v?V?7 ;8??????n????G????qk?]??f???O{\?G~?]5??t?6?>??e??(???c?? +?$?tV0???? ?g]??P?_?OUl??????G???????P??,?A2?c?c }\??LtE?X?:5?????yFA?? !J?????????na???6??j????????=??2S?]0??~???F{???z????h??O?+J????aL?m ? ]O1$??'?m??)mS?77 ?\?6?\???o?????i??}z???z?B?+???BWl?u??/???? ?,?ab??]a?? ?????Vz????X??+????]?t?1?F??W??_H?A?j\?w?gv?3ab??k??P??}Y ????j?*p?{?l??7??7???.!>I'????!???l?\?????kG???tBW???`?1h??p???????7??L4endstream +endobj +273 0 obj << +/Type /Page +/Contents 274 0 R +/Resources 272 0 R +/MediaBox [0 0 595.2757 841.8898] +/Parent 283 0 R +/Annots [ 276 0 R 281 0 R 282 0 R ] +>> endobj +276 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [100.0827 750.9806 113.1137 766.9208] +/Subtype /Link +/A << /S /GoTo /D (page.47) >> +>> endobj +281 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[0 1 0] +/Rect [364.5084 330.6422 390.7497 340.1764] +/Subtype /Link +/A << /S /GoTo /D (cite.VMC) >> +>> endobj +282 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[0 1 0] +/Rect [387.7614 278.8365 416.4832 288.3706] +/Subtype /Link +/A << /S /GoTo /D (cite.D05.1) >> +>> endobj +275 0 obj << +/D [273 0 R /XYZ 74.4095 738.0292 null] +>> endobj +277 0 obj << +/D [273 0 R /XYZ 74.4095 720.0964 null] +>> endobj +10 0 obj << +/D [273 0 R /XYZ 74.4095 720.0964 null] +>> endobj +278 0 obj << +/D [273 0 R /XYZ 74.4095 696.3583 null] +>> endobj +14 0 obj << +/D [273 0 R /XYZ 74.4095 696.3583 null] +>> endobj +279 0 obj << +/D [273 0 R /XYZ 74.4095 535.0903 null] +>> endobj +18 0 obj << +/D [273 0 R /XYZ 74.4095 525.3494 null] +>> endobj +280 0 obj << +/D [273 0 R /XYZ 74.4095 443.4516 null] +>> endobj +22 0 obj << +/D [273 0 R /XYZ 74.4095 425.7406 null] +>> endobj +272 0 obj << +/Font << /F26 180 0 R /F31 192 0 R /F14 259 0 R >> +/XObject << /Im1 171 0 R >> +/ProcSet [ /PDF /Text /ImageC /ImageI ] +>> endobj +286 0 obj << +/Length 3553 +/Filter /FlateDecode +>> +stream +x??]??6?}?????????S?>_9?\9???!???;? L?z????@0???*#Z?V?????E??v? M?'?Tga???a???5????MUV?????T"?8???+??P?(:6L???v??wQh?? a?c???F??????wV?7???7?_???4 ?Xi8W??????g?;??????d??????|c? MbSin>??4?YZ?%?$?????????)D9\a????p?Q|?r???SS?=??[?^???ao??u? 3k????? +??,8???18?X?K?[_?`?+???(;???n??u??<n? 3\?2q???,o*8r?????|i?/ ;????& +??*N?L:1?;Y?s?o}_??65Kfw???&Q???I???J?7?d?UNd8u?w?c?????4x?KJ??????5 +Y?G?=?a?#O???????{?}<?|?U=??? &???l???.*???i??:?b!?:?$??X7?iwRy?f??, ??Pn??NC??Jv??*E?9>Kw>??.T???IL????E6?F??/Mg??i%P??o(???_???B +"6?Oa +?p?e????`????gc??H?D?G??g ??N ??0??<[:?????'?-?????Z7^2????/O?U??1g????Z1.? ? ????QO?,?tm???????????@??????\7*?????I??????u}?OW]R?Bk?>^??j?LX/pct%Kn??????& ??Z?[???K???H?U?????'NHW???7@Dwq???X?W?}? +??? `??6|??Y8i?F1??(~?f{??????l?$ +?SU?p?????.???2??d??W m ]A?3??hW`????1/.???NP?G??v?R???M?v{&u?Z"q9???qnf??+9Q@???}ynD?:?k???Nr?,0?SR???=????W??y6???Q???U??P??~???x/S? ?~?????U/?~xj$?y???Xr^???? v{]??o??Z ?X? +|???) }B[?$?H????? +x????RI6S??va?4????'?~? +?% ??9???Y???Pm???}&?????? ?!??A???L?????9??????o??T???????)?lD?O????S#t?a??F???/D?Il?]0??[?????-?+?HF?B=L??T??8?g??_?K7`???|??R??j%?>;??a?f?4e??]?v??6i'??????3??K3????'??G/?I????%V?u??7v?zq?(??@1F?? ?~w??M??L?i?~nh????????#??????yz ??z?<????;;s??$DgN?j?$??l?r??E??n???o?h ?(???3;?_?u?4K?,Yg??P?~???I?N??O??~$Hk??Q?E&?h?????w06?9??????_,???????a??jM >??????JC???EW???M9*"???????sUh1$D?`???\?*???????oq?Z??z??n???t?$??2Id?*?C"???~b?R?'??&nL?E ??? ???????+cu?????o'?_????? ?Eendstream +endobj +285 0 obj << +/Type /Page +/Contents 286 0 R +/Resources 284 0 R +/MediaBox [0 0 595.2757 841.8898] +/Parent 283 0 R +/Annots [ 288 0 R 292 0 R 294 0 R 295 0 R 296 0 R 297 0 R 298 0 R ] +>> endobj +288 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [100.0827 750.9806 113.1137 766.9208] +/Subtype /Link +/A << /S /GoTo /D (page.47) >> +>> endobj +292 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[0 1 0] +/Rect [121.6144 653.6008 144.588 663.1349] +/Subtype /Link +/A << /S /GoTo /D (cite.SLP0) >> +>> endobj +294 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [365.0223 378.6794 432.6396 390.1762] +/Subtype /Link +/A << /S /GoTo /D (related-work) >> +>> endobj +295 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [477.2303 267.068 521.8625 276.6021] +/Subtype /Link +/A << /S /GoTo /D (stackless-transformation) >> +>> endobj +296 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [73.4132 255.1128 145.3525 264.6469] +/Subtype /Link +/A << /S /GoTo /D (stackless-transformation) >> +>> endobj +297 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [434.9917 187.6159 521.8625 198.8935] +/Subtype /Link +/A << /S /GoTo /D (application-level-interface) >> +>> endobj +298 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [73.4132 177.4042 119.0416 186.9383] +/Subtype /Link +/A << /S /GoTo /D (application-level-interface) >> +>> endobj +287 0 obj << +/D [285 0 R /XYZ 74.4095 738.0292 null] +>> endobj +263 0 obj << +/D [285 0 R /XYZ 74.4095 720.0964 null] +>> endobj +26 0 obj << +/D [285 0 R /XYZ 74.4095 720.0964 null] +>> endobj +293 0 obj << +/D [285 0 R /XYZ 74.4095 491.2397 null] +>> endobj +30 0 obj << +/D [285 0 R /XYZ 74.4095 473.5287 null] +>> endobj +299 0 obj << +/D [285 0 R /XYZ 74.4095 178.4005 null] +>> endobj +300 0 obj << +/D [285 0 R /XYZ 74.4095 178.4005 null] +>> endobj +34 0 obj << +/D [285 0 R /XYZ 74.4095 160.6895 null] +>> endobj +284 0 obj << +/Font << /F26 180 0 R /F31 192 0 R /F34 291 0 R >> +/XObject << /Im1 171 0 R >> +/ProcSet [ /PDF /Text /ImageC /ImageI ] +>> endobj +306 0 obj << +/Length 3401 +/Filter /FlateDecode +>> +stream +x?????6??_?????"?z&????Y`?If{?? Kl[?,yL9=??[/J?,wS?bY?7[mB??6Y?a?l2?aTD???n??A ??!?|?~z???(??8?qm>=m?0?yD?"H????????/??(???Y????8???????1 +???p\^??5mcO?x???????m??K?C?w ???M5???????_??A??f`?f?tP?YF? ???m????O?B?Y???$HR???r9??? ???'???P?=?? sJe???B?#?[Lo?!?w|??LeN{s?/??t??rWq?????A??1??|??A w?????\?n???'?????a??t??A) ?*??????? 75????=E?l??U????8 ?$??L???a??Ai???( ??V{gB-A+?s????o?5?R+?m??W???hx??/???Y?_/???A???O??BF#?c7???U8??B??????G?l??? z`??o?fxP?{?j?a?I?Y??.????lCO?8???`?#???g?WS]???G? ?l?w?x~?0nO?J? p;??0$??k??l?7)D???? ???L??t?C*:$?=?&as:?M? ??-n??e'??b0??By???|*???????hxg????FP?r(1????$?`?m$aL??tl?T:??o???O?xH!???C??KZ? ?8????n?'R??9_????F??M? ?y?\J????^?#?KA??nh??nU???%???4??Gv??~O??????7???M??a???( H? ???f?aT?? ?5??n(???BA??e??5??br???bW?n?mY ??????T?mm??j??S?N?sYj?w? ??>??? ?v?e??P??? F(<7?1??Km?wL?Z???`????r?L?R?'^P2??e??o:?+0????? ??r?|?$qF??K:@o? ??4????-i?????.??????Xp?ZY???5?(??z???%rB??-???3?@?EMG??rre??Q&??\??p???#F???_?&??G??vh*?S6S{#D???i???5J?[QS????Np??5??4??d([I?????7?:?*??p?u?? o?(@?J?e?@???????b? ???G?@?)V???8S5\?_O??????!?)e?o????fK?5??eR???Q?kq?U`*f?;????9??~(?L?3WU?G~ ?????t??v?l.+??d9??KP??.)9_??oT 6ul?m??[?.??D?,??]G?A??(???????"LS?*M?? +?sK^?MM???|@??????R?Zx))??gJ?O ?????|??y?R??u +?A??????!6????{n?????mT???:|?T??AG?KzO?jR??'??SY??|2??????J?Y? ??@z??? K????++|?]? +w??S??) ? ?nR!????W????D????sI$j?y?%*(a?.??A?<=?'I A???@??O???o???????T?????0??????C????"?t?Y? k??/?A?9Y ~{%N3??Xs +pQ# "y?\z?8a???S?$.v??f#?>Or?r+???wr ??%?k-)?Z?????Da? Q?'?Ro??$ ?E*D?6$^vRW??I?9o?)^aR??\0Q?bi ????:kx?m??#5???9? ?0[???Q?<?Eq?=W#?-?? +?i?[??PK??e???fU? +|B?&?g?g?????P??ht??0?????o4 +x?3s? +?T ??gD?????T +O?F+e?sR?t?_M1J???????E+?????C3??N}????q????????q????????gG:a??$(???#e??h?I?-???WHvA???v[?W?{?5??????u?`o??????????D??M17I?????X:\Ns???;5?*??L?????0??0?^???$????5O??F?+>~?D??Y??/fW?m ?2???w?5g?? +??_?Z??t^h?N?3??E1hTE?ze?c???F??*?W???? ???h?T???K?jE??[??? ??jW_n????8?W?~???pW???0*?????p???}??$?%?u??L]3e{`????*???/W?????n???u?j??[?z?^!?:Y~?_+'8f|?6b8Kn?0??????Ki?????:$??? ?$2s_??? +%2???1>$??+?^@?] ??k???y*???B???1??>z??????7??B8???+?N????s?C?l?C??=? ???V??> endobj +308 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [100.0827 750.9806 113.1137 766.9208] +/Subtype /Link +/A << /S /GoTo /D (page.47) >> +>> endobj +307 0 obj << +/D [305 0 R /XYZ 74.4095 738.0292 null] +>> endobj +309 0 obj << +/D [305 0 R /XYZ 74.4095 536.2222 null] +>> endobj +38 0 obj << +/D [305 0 R /XYZ 74.4095 518.7457 null] +>> endobj +304 0 obj << +/Font << /F26 180 0 R /F31 192 0 R /F14 259 0 R /F36 312 0 R >> +/XObject << /Im1 171 0 R >> +/ProcSet [ /PDF /Text /ImageC /ImageI ] +>> endobj +315 0 obj << +/Length 3996 +/Filter /FlateDecode +>> +stream +x???????>_?[8U+??W|rb;???>Pf??"?"?????_A??-6 4?o@???]ab?T??H?8???5??d? }{P??wH??/??V?;e???z??iW&qZ@4??L)??????q??$?:)b???}j???8??uY??????:????C???v??#??_??????????i???t5?m?5??8???$??????[!?_????<^Na??%*??O??'?^?0< ???D?52+f?A?????Of%?=J7? ??5??/I??n?3z?q'f??L7: Ty8?n?i??;>6??c2G? ^???Z?~?L?k????n?^ +RU?&&?z? D????.IN??{n,#?VNI?8+!?I?????=+?b`?32Sn??9m?u???Jt!?W????-m>Z????(?'?=?cq?G{???) E?$j&7f????_hW????>????$? Ms?????uyT?"N?2??d?)/N?????0 ???$?5????I???#?B{?????????tib"Y?Z???S???D?7????D)??????/I??}O?^F?a???/?s??n???i??????lu???h??h?bT?y ???"??L????At?????+?????U)??b??H(4'eNZ??? ??h????y8???%L?Wx?>??Hu????e?4??T?@?]?l?H\??\?K?,?-??)??>??c?j?5??\?????rC%?@?7C ?????*?.I??}Q$???(?A??9tH*1?G????'y3l??$??(?;?B?'O?\m"?7?????p??Qe< ???????M??JW??' +?5/ Ad?b???E??D~?#?????????????>?GF?????xO??-a\?j{??G?Uq???w???# ???0????a????"x2W????h?Y;?"???;?????"?lY??[5?mMU?>?T?? [?:??Fu??b??? ?^???}?*?Yz??????.4m?? +?\*|t N???K?WU??`+H???X???b??l??>M??`@????$??V??????r!KU??? h???M?I?"??????C??m?8?3?y?{y`???C??|Z?r?R?;#0/r7? ?H??? T3?5!a? :LVcZ????R??]???IW'o??*??D?p?h?????????LmQc*?"??? +?:?#?p? #Vl,?+?)?kKa???????~^?,SS???L??*7W???????????+?k?T?~???????E?$Y???@z???{G g?U?a??? ??Ap??'??????E?TKAv?=?Dn??0???? ,Z?D??G$=??;W`9r??0?\??YHd>C"TO?0L;?? ?p??s6?-|N?*4-?UY??? ;?D??????'???h??????????xh?????????@?b??c|?~F3??p0N??U?8"??j??.???5G9F ? ??/Tz},?cC??????P?lxB!'?s???T?%??]L??$?^t???$?v???p?FX??(?m??fVC~? l?m&r.??q1???#tbw?PN3)F????????bQ? ??@?X0????)V?J??????]??]???k??t??:?3x? +??E2???????h??w???????????E5s??@/??????\?\f????S?v?K??L?\??????D???T???94]?i^0?*6EY|?^???????.?????????G???????L?Z???z?????26i?\?????????????L?i? ???s????b?? ? J +?}?k!%????J?%9??Z&??????????n?`Ia=Ns?Kz?g??Y??&??"?7 ?8W*)?r?????v? ?>???Z???K????l02`0?S?( ??$?????Ab?&?C[????H#U???qaH`?6????B?? E????z????X?}VR+_????????4#?b??5? ?E5!n???? ??uf`??????~?%W????g?????Urz?????{$?r??????/ }?D=N???L(?????????7?(F????J?.???"T??U???????;??????X'e\B?-?.????r????|U,?#??C?"??e)k?"?R? ?&?U??E???Y?X?0?????U??(LB|9???_??w??6?( ?2??2:v???u??P? ?????W????~y????M?/%?RL?_j?y???6-q???E??==|??"??T?;n?u ?'?_?????Nnn\?;r???a???1t~?IN????P?f??]p?I???IZH???^?????sq{?vl?_??GJ?t?]P?????i??Bu??#C$?$??`?TY??5?G$ ?8m?????* ??????+??o\??/????)(s??#??L?b????????v?????|???O?}*,`?hqN ???+C?U???[ZG??X????@?KK!?< 2??R6%?Fi?[?^??=??*C?1I?w????}%? +?A?Z???I???\o>O?????k%?endstream +endobj +314 0 obj << +/Type /Page +/Contents 315 0 R +/Resources 313 0 R +/MediaBox [0 0 595.2757 841.8898] +/Parent 283 0 R +/Annots [ 317 0 R 318 0 R 319 0 R ] +>> endobj +317 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [105.602 750.9806 118.6329 766.9208] +/Subtype /Link +/A << /S /GoTo /D (page.47) >> +>> endobj +318 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[0 1 0] +/Rect [346.4438 434.0641 380.1967 443.5983] +/Subtype /Link +/A << /S /GoTo /D (cite.PICOIL) >> +>> endobj +319 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [326.3722 348.4153 416.211 359.9121] +/Subtype /Link +/A << /S /GoTo /D (unbounded-stack) >> +>> endobj +316 0 obj << +/D [314 0 R /XYZ 74.4095 738.0292 null] +>> endobj +320 0 obj << +/D [314 0 R /XYZ 74.4095 116.505 null] +>> endobj +321 0 obj << +/D [314 0 R /XYZ 74.4095 116.505 null] +>> endobj +313 0 obj << +/Font << /F26 180 0 R /F31 192 0 R /F34 291 0 R >> +/XObject << /Im1 171 0 R >> +/ProcSet [ /PDF /Text /ImageC /ImageI ] +>> endobj +325 0 obj << +/Length 3385 +/Filter /FlateDecode +>> +stream +x??]??6?}~E?-m????)?lN??&?(I?bhO7?4?vv???? ??gN?Yp?lW??w? wi?GA?R????????????.??E:?X?????;?????Q?v???,?u???I??a??????/????? ???????E?W??*? O~?????kSW??C??:???????!???mx???3?????????t???<b??`w??GiJ??!,HS?}D????[a??q??]?~???y???????Ha??? H ??E:????0?????W????:?j7x(?m??9?# "??_??????i[U Fl?????????mS?0?l/]m?c? OdM?O??3??p0 +?w]]???U?Uv?????r(??????E??? ?p3??L1???wVx???? ??#! h?? +??????4 +???? PH????"?a??E?pW?q??U#SE#?????X? h?A???????} ?????x?1?J*ek??c 8d? ??a??^??d?W??????{Y?6>~??? ????:??G???i??k???@?vH??? mutL????e??tl?q\Q?*?????S? ??\?kxS??ZTG?H??6B???? +?????????z#?M}??9?~g??9?rZ????p???LZ??V? ~???/??^A?:???* ??????*a-?P??vc?~?U6??^/]U +S0?????E9U?J?1 n?eR1???P???/?G'&r??1???{}bie????tU???e????u?IX??BBf^????zt1(0????????#???n3?:P??????????Y????r??r?R?????j??0U?Ck??G(??H?JI? S?pc#IN?w?????/??-??????e???O6 ????k??mK?&?M/?&b?4????j??f??m;?%??4???????V??V?=?#??????g???/??%y-?4??h?n??F????z??ZWMaH????0?= ?=?????>????]_wvq??--??x* W???!C6s?`*? ?a??{?hZ?Xn?U=?k??&??4p?XA?k=?E???@AO?'{?8??s? b ?]?Tf?}????d?i\o?!}[b/S&?? ??c?:9L????Z????{c?"0X4 {? ?J??T???qb??M?i?L?wGiE??=???p??/#???Jb?V?Z??z@????b?????E2s??5??K?d?`-?|+???!??uR?J?v];??L??v???#?????j??[??B?V??????????D?z??E?~???aa??H????],?T #?e??c?{Q?7?.D???*?{?P?t}?v?m??I?<E???H?G?nx?,?? ??t??h??:????f?z??`8??&'+8?r ????%>Ls????%?8?????>FE??~?L /o2 .6?K??O?|??????D?{??\?u?S????n???9A3OmP6sy.^?W?Y?? ?R??1^U?q?o????K??}???B??Y\?T?T?a?D+?V +>a?A????dI????K?w ?O??7?>????oX????? ??6??????N??x?D6??',???????}???i?4? ?]??jg:I;??8?C=???6???#????}??@@x??a???_T&zF2?>@E??JO????&|I8??^?*???q??Kxrx??J: c?~aN????)6?^?R0??>?i??1'X?[?????h??b???????DYT??"6??}???RL?????????\BS?I>Tq???3Z?e%????????> endobj +327 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [105.602 750.9806 118.6329 766.9208] +/Subtype /Link +/A << /S /GoTo /D (page.47) >> +>> endobj +329 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [183.7685 166.4466 273.1427 175.9808] +/Subtype /Link +/A << /S /GoTo /D (unbounded-stack) >> +>> endobj +326 0 obj << +/D [324 0 R /XYZ 74.4095 738.0292 null] +>> endobj +42 0 obj << +/D [324 0 R /XYZ 74.4095 720.0964 null] +>> endobj +328 0 obj << +/D [324 0 R /XYZ 74.4095 355.8037 null] +>> endobj +46 0 obj << +/D [324 0 R /XYZ 74.4095 338.4498 null] +>> endobj +323 0 obj << +/Font << /F26 180 0 R /F31 192 0 R /F14 259 0 R /F36 312 0 R >> +/XObject << /Im1 171 0 R >> +/ProcSet [ /PDF /Text /ImageC /ImageI ] +>> endobj +332 0 obj << +/Length 2550 +/Filter /FlateDecode +>> +stream +x??Y?????_????Y!)????C?4E?5?[?w??V??Jd?g?I???|P????4??(r43??f??k????El?a?B?j?Wb?k?ZIG?m??}????^?Uv-?h??w?u$? +???}#%??~?????lU$?7"????m?C??I]??7Jx/??qrN?"+?????m????.???xM^????>eiSo??????@?c??? (!?[??C/|?^?G?????mIa}Gj??;.????:?m?2?@?)_?C??2?m`?????;???N???x?o?4;>dg~??M+!?X+m?D|?F?Fq?????pn???cX?s%u??K?N?zw??7???????n?0?c%?W?KgD????X?`??????????A?2W;????6?57S?~]]y?V??9#%??Z5??#v? ATDd?????Y??????s ?rT?????N??? 0???/j?3????>?~m?Fhbh??????b]](s@?9c_H??h? ?Vv?LB8??,???v????5Z?v???K??\R???g??7??v?]V??????_??FE?@A?L??????z6???^?o,t?B?6Qx?I???L?????S+|w????6????X??? ?J:??;RS?x\?9_z8)??C???????^?s?????_??? 59?U0y?j?????I?V|c1.+0?y?~h?[ +]??K}.24?W??p?Xq???I?P??8o?]?+??7?j'?;.p?X??5-????F??k ?Gh1??t 9???# i/?t?g???u????a???$?????????3q??:?n??F? ???0@????u?%5??j??E???o?????|??Q0?k+ ??]? +??N??ZT??D??o???g.??????> endobj +334 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [105.602 750.9806 118.6329 766.9208] +/Subtype /Link +/A << /S /GoTo /D (page.47) >> +>> endobj +333 0 obj << +/D [331 0 R /XYZ 74.4095 738.0292 null] +>> endobj +330 0 obj << +/Font << /F26 180 0 R /F31 192 0 R /F14 259 0 R /F36 312 0 R /F34 291 0 R >> +/XObject << /Im1 171 0 R >> +/ProcSet [ /PDF /Text /ImageC /ImageI ] +>> endobj +337 0 obj << +/Length 3769 +/Filter /FlateDecode +>> +stream +x??]??F?}~????Hc?MC??^r?6R??f?{H??x?-???;??W_ ??h?CVW?wU[????$ +"?????? +?pU????~???f?m?U?~??????t??????*U?Ij? ??v?????{????Z??@??~c?d?S?u???P?K?|?????uYW???G??Z??????M??????7??,?????????Ud?$?j?M?EIB?k?d??q???kie?8K?U?AlM?w?????y?QaX??7&\?E???+???-???? ?J?9VQlcT +pl??i???>?T?"Z??a????2??????Q??k?~?[?2??$i??????@??#???j????x????32"????.?l?p5??~?az??u??q????pA?'D?A?Q??D?o?3?f{???5?v]5]?7??u???h]v2?K??7??^?k7q9?????!`??p?O???c?????? ?? R? ??f??|??Am???cL??\?n????}?0?5Fk"?"dq?? ? D?"0g#`hH~??,? ?L`?)tRQJ?&??E???[X?+Oe??)??????????????m-???????\????VZ???s?????"??????KHb?0?@??R??ew9?At j|#0?a)???{Q8?<?v?8?*?;????=7???????&"b??????K-?W??? ?\pF-??yb?E???K????.?]&??6?????'q??`??????P????/??= ???:?????x??t??? z?av?u-??? ?????IZX? +?.3?2E?E?P&/?I??65?.??v?Q??zi??????8??KY\H????@?d??(#KH?? ??r?!?1??????.?@j +?M?????? ???8?kRr????????Y?)?L? ?"o???8l????,NH$??[??A?$?????e???P1?????|??P???9?k???a??r??w???????R?S????0???W??0|-6s?7????h?:o?'K?8??D?*??1"???!??Q??28????]Vm?eK9??n1?y????db?)?y*?x 4[??S?W??`????R? N??[nX|?v':H?M7??X?3?hM?????%Ss???T???q??w???N-???#0?]:,?`G?K 3??p)2 ?a?]?s?8??ja]_?R?\?n???Y?q??j????W????y??? ?jt?lv`4?wC???*?)????9=?J??Mh?Eq?[???AG??d??v?z? b{+?????2?/??D6P?p?W????E)????????? ??C???$?Mi???? ????S7??{v?J??????????q?8K?z= mQE$?~+??)1;W?%?z{??sWFR???B?v=gt,{e???????o?/'???????m???2F(?|{?3`?e8???VF?(S6T??PN#?a???_?~%??W,?_????t?L4>?/s?=?????_???Q????FO?{wW=7> endobj +339 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [105.602 750.9806 118.6329 766.9208] +/Subtype /Link +/A << /S /GoTo /D (page.47) >> +>> endobj +340 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [432.8548 671.2048 486.6425 682.7016] +/Subtype /Link +/A << /S /GoTo /D (coroutines) >> +>> endobj +342 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [471.9402 502.0767 521.8625 513.3543] +/Subtype /Link +/A << /S /GoTo /D (coroutine-pickling) >> +>> endobj +343 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [73.4132 489.9024 111.3607 501.3991] +/Subtype /Link +/A << /S /GoTo /D (coroutine-pickling) >> +>> endobj +338 0 obj << +/D [336 0 R /XYZ 74.4095 738.0292 null] +>> endobj +341 0 obj << +/D [336 0 R /XYZ 74.4095 612.6445 null] +>> endobj +50 0 obj << +/D [336 0 R /XYZ 74.4095 594.9335 null] +>> endobj +344 0 obj << +/D [336 0 R /XYZ 74.4095 192.2386 null] +>> endobj +54 0 obj << +/D [336 0 R /XYZ 74.4095 174.5276 null] +>> endobj +335 0 obj << +/Font << /F26 180 0 R /F31 192 0 R /F36 312 0 R /F34 291 0 R >> +/XObject << /Im1 171 0 R >> +/ProcSet [ /PDF /Text /ImageC /ImageI ] +>> endobj +350 0 obj << +/Length 3647 +/Filter /FlateDecode +>> +stream +x??]s?6???b?Wy >??Sv7??*?m6???????&?u~????`;?*??n?Vw??D? ?/?d?y?????(?6??*????*??!??To????>J7a??8?6w?Jg0i??Il???????z??{d~?????3???????(?*F~?q?X4M??????w?*???o??m? u?2???T?C?????|??M??)0L?m?????,???????n+ R??u????OR????????,??}??0c?|^?#???3?Ui?X!{K???g???7??wUY??G~ +GA?.???+h?'?3?c\n??&?c?[LT??\?q????~??1????~???2?Fe???P??r?L at G???/?f{??XP???*?s0??U?~????\?z5??`??5!&Q??4?V,x&D{BXJ)M2?[?56?Tye?C?Mc?,?W?Cu???U???^^`????????? +?TQ???zM? ?s?U ?>?s????????!ug12 ?{???t_?y at 3 ~`??r?5By????:???3?????b??6t? "??/?!^1G?;5EY???z b?M??b????(Q?????{|&U??sD?.+?_??X?k??c/{P????+n?n_???????h6???b???b|???? ??u?8????Y?4??i?H?Q??M??~???????u???????s?Nz??e?????????.1T?N?????@??$3?iX?-6?Y:?, ??OP???;?,?Z??r?f ?JRSD$x?????A??,?P????G?b????????#0?q????????zT?;?Cm[-7R??v?CD?\U?]?o?;???? ??EJ??tX=y??Z??#????w?|??????c?1> endobj +352 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [105.602 750.9806 118.6329 766.9208] +/Subtype /Link +/A << /S /GoTo /D (page.47) >> +>> endobj +353 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [409.8793 629.5016 521.8625 640.9983] +/Subtype /Link +/A << /S /GoTo /D (memory-management) >> +>> endobj +354 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [485.3695 617.5464 521.8625 629.0432] +/Subtype /Link +/A << /S /GoTo /D (finding-roots) >> +>> endobj +355 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [73.4132 605.5912 98.4987 617.088] +/Subtype /Link +/A << /S /GoTo /D (finding-roots) >> +>> endobj +351 0 obj << +/D [349 0 R /XYZ 74.4095 738.0292 null] +>> endobj +348 0 obj << +/Font << /F26 180 0 R /F31 192 0 R /F14 259 0 R /F34 291 0 R >> +/XObject << /Im1 171 0 R >> +/ProcSet [ /PDF /Text /ImageC /ImageI ] +>> endobj +360 0 obj << +/Length 3576 +/Filter /FlateDecode +>> +stream +x??[K??F???????]1?'???I?H??8??=$9p$jD?"?!?x??????lQeduX ??_W?W]???"???Ht???,?F???bsx?OP???m???:l???_??v!t??????EG*M`P?EF(???|???e??i??:N"??j?t??>o???J???*?b:???????w*}?R??9??*_???+??*^??b???_???%Y?Y ??Z?(?I??:$???a??o?????L??EbLd?2?v?z~?6?R????N g.?E:??_$?U6???}?????????]l??c?L9a?X????FEJ?)?c?$M5N??}G??]?0 ????Qw??/?=??????????$?2)?+??????/????????,?@ED"S;:?mN???cU??@?S`p8????x?D I{??f?~?-???/??s?'??Ub????#?~??Uj?8??9?#J?????B???H$F?k?? ?:??x$????>^???c5FFZ?{?? ???? /m& ???5??I +????? ?????K?w[z?v?k? ??-g???F"M?9?L?D????8???A?8?Y?2Rq??cJ?WIx7?g!?$??q? ????????yI?&IoPVk?h???@??]?F=??????Y??B?0p???N??? 7?s?\???s????s? ?? U?f?Yw???5???!? ?YI<]??????J??oU??WILv/??H.?)V?6A`??8?? y??Y?/C?6 7????????w?0u???3?C??$??????YsW????[??Qff??{v?8???M??????<&??g?2?8X XW???:g??2??,???L???Vz7?Ag1 0j+??l?????J?????i6?$??I?q'?+? p????K?????????l???d??< ?,???!tX?v+iol?w?px?????d?Nol????Y?Zd?M? VKI???????+?,??????zz????s 8?D?q,??{/?_?Pt Q?8??`?1?????!D?f3?Cw????C?D?d=?j?d"RI&?rK$`?}+???????"?bf????Y)????n:?nYo?????(???? ??5?????7J??_??.? ?n????bi??? ZM /M????ge77? ???{??3?v???1]?Z?T,??zY i??j????????????,?/???Tqe?p%?sz??u?N?7???????9Ne???n?1}pAU?5 +?q?F?F???+#???&??e?='????E-?7M??e?R.?G}?7????R??m_??Pn??zY;s???????#?}???????"????P??3I|Qh?????????`>J8??c?????fO?}?_?????.?]???a????g????????[?Qv{?o'V?x??U?._#,??i)???(?x*?n]???-?$&?V?$ +ZM???????g?f?Es3,???gQ8??????4f,i???????u???v??}??n?]o?r?6T?[iB??????}??vL?2?u???U????H?????????S???d? M?m???-?#???Q?)?vk?Z???c??X~,?~k?g#mO?????????????K;l?????????y??A???}?QE ??+=4-?C0a???l?]9I?C??%?pd[&???+????????Zt~??r?z?7:??P??;??]:??k\nKY???x?ji@?9\q,?,YS??rT/eq?'????f?\%v???Q??9?xr??????(?????p??9??4`?? E?h?5=?MY?X??jPw????E??????+8?????@?}??l??7??g??F"NhCx???cN`????x?9'>)p?y???}??H??[????i???(?R?-?!?? +g V?4?7\Z|dVb??9[JS ?)?IQ???1??]?? ?R?/ ??????V??@??b?W +? ??m???r[?w1??Q?????G????9FnNz?w8?N???????Z??m?6'???????P??????~T(??'??T???OIc???o??-????@????@Ik{??S??[?$}IT\?BZ*&?B??szL??H??0?Zn*?? i? ?????)?????DV???Cb7?R??z??TA r??*|???CH??~?????B:$Jyi?W???eU??Z?????????X???? /?z?n???)? ]?8j??;J>?????[{GJ?qG??t??Z|??@ >????????M????R?U k? ?q7+endstream +endobj +359 0 obj << +/Type /Page +/Contents 360 0 R +/Resources 358 0 R +/MediaBox [0 0 595.2757 841.8898] +/Parent 345 0 R +/Annots [ 362 0 R 367 0 R 368 0 R 369 0 R ] +>> endobj +362 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [105.602 750.9806 118.6329 766.9208] +/Subtype /Link +/A << /S /GoTo /D (page.47) >> +>> endobj +367 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [376.3505 371.1302 521.8625 382.6269] +/Subtype /Link +/A << /S /GoTo /D (microbenchmarks-of-stackless-features) >> +>> endobj +368 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [73.4132 361.1376 116.0529 370.6718] +/Subtype /Link +/A << /S /GoTo /D (microbenchmarks-of-stackless-features) >> +>> endobj +369 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [378.6507 128.0593 450.2912 139.5561] +/Subtype /Link +/A << /S /GoTo /D (composability) >> +>> endobj +361 0 obj << +/D [359 0 R /XYZ 74.4095 738.0292 null] +>> endobj +363 0 obj << +/D [359 0 R /XYZ 74.4095 720.0964 null] +>> endobj +364 0 obj << +/D [359 0 R /XYZ 74.4095 607.3194 null] +>> endobj +365 0 obj << +/D [359 0 R /XYZ 74.4095 585.3269 null] +>> endobj +366 0 obj << +/D [359 0 R /XYZ 74.4095 529.5361 null] +>> endobj +303 0 obj << +/D [359 0 R /XYZ 74.4095 362.1339 null] +>> endobj +58 0 obj << +/D [359 0 R /XYZ 74.4095 344.4229 null] +>> endobj +346 0 obj << +/D [359 0 R /XYZ 74.4095 129.0556 null] +>> endobj +358 0 obj << +/Font << /F26 180 0 R /F31 192 0 R /F36 312 0 R >> +/XObject << /Im1 171 0 R >> +/ProcSet [ /PDF /Text /ImageC /ImageI ] +>> endobj +374 0 obj << +/Length 2967 +/Filter /FlateDecode +>> +stream +x?????6??_????`?XHzNN?$SS?L???8??(??1E*"????y @?[}p?x? +?E??H??Qf?JEg??8?E????Nz?uZ?~??{?1? ???6^??,?H?4?6FJX???????y???h?!J?|?Z+?,???m?mGK???p????rU?????JE?S^?U?Z?eW65o?o????????????"?a@?h??Jd:I?????$??a?~???%#+L????a?2|v?:??6???14EX?l?????)kO)HI?LXU?CL?5?"u?????y1???bS?????IC?.&q??a`?????2???>?58????Xc?`;?V?gW???????? +?t* ??KZ04k???)-X,???)c ??? +???.??k???&??a?b +.????? 5?l? ??/??D??(>~"?4?9m?.?%????/q??*k?kLz#1?4??A????>?x??ry???m?w???3??????[??cE??% W![n??X??Z?? Pv???RTM??x??u?D???=z???k?}?c??S??~=???,6e?EF??7?m?$ ] \74k???@[FdI??e=??ZF?T?Zc?X?x???????m{+p?$?L?+p i?=??cI?> ?L?? +,?M??C?????????? +n.????+?O???2X?J$Y??2? W`n^???9?^?D7q&?4?j?Q,?Z???? J 8?{U? FrD*6???/?/?Q???L1?? H.?4???????t?,?????=??o????g???E?,\:??aR?(f?cM?*L1X?)??Y|m6????????csf????(??a????UYD????&?'?????? ?>?@?? +??vO?h*?]??[??vX??????b??um??&- j?????4G? ?2???b&j??KW?d4?H?.7y?5?W?#9er??2?*?M`???I???:'??? =t?L????????? '$?-?9???oK?P??t0n(????a?wx??i?S&L???f=?V???3}?? ~?????i?E???m??5? ??-=z???73?-S??0L?MA?:w?x????U?E????d0????h?6?B"# ???%/\OvF?t?d?????????vq???9~?r???^??7??i???l?1}!???\?/??'?H????*u~V?c?c???:?7B??,???ON?????fx??K+????z????????g?=??N)c?d.?*??H?y?%?^YG?Vo????W ???N????)?W(?^3?8??????!??????.????h4??Wn4*?Px?U?0jj???VE?? ?????O?s???E?????oR????? ????~uB?B)p??K???Z??Ii????G?8r?>????F?GA?.????????o +???k????R?RH???YgF?I??????????r(n????p?)?=?1C???;g?????=>????????5?? wz -???x?1?wp)?^?j^?????L?hG|??m???r???????y??Y??????#6<*F???@5?!????P?Z??y???L??W??B?  D?XA????r???k?)?g"Bj????,;~???K??"??\??(|VO?9W[/???_?m?? ?H??U?# c?/?x~????W?hN?#?\???On6?u%xl? 9?O?C/?? +???6sm#?IV*?j?5Wr??JE????N?????B???!|?`p??g???g???r?B@??:??S?{???C4?)??????R??OyV?x????????ay??endstream +endobj +373 0 obj << +/Type /Page +/Contents 374 0 R +/Resources 372 0 R +/MediaBox [0 0 595.2757 841.8898] +/Parent 345 0 R +/Annots [ 376 0 R 377 0 R ] +>> endobj +376 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [105.602 750.9806 118.6329 766.9208] +/Subtype /Link +/A << /S /GoTo /D (page.47) >> +>> endobj +377 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [361.6489 621.1874 433.2894 632.6842] +/Subtype /Link +/A << /S /GoTo /D (composability) >> +>> endobj +375 0 obj << +/D [373 0 R /XYZ 74.4095 738.0292 null] +>> endobj +62 0 obj << +/D [373 0 R /XYZ 74.4095 720.0964 null] +>> endobj +378 0 obj << +/D [373 0 R /XYZ 74.4095 227.8301 null] +>> endobj +372 0 obj << +/Font << /F26 180 0 R /F31 192 0 R /F36 312 0 R /F14 259 0 R >> +/XObject << /Im1 171 0 R >> +/ProcSet [ /PDF /Text /ImageC /ImageI ] +>> endobj +381 0 obj << +/Length 2308 +/Filter /FlateDecode +>> +stream +x??ko??????~883?H???w??b?"?MQ?EA?LL?,?D*???w?C???$Ea??????(?L????d2??e)*?fu?l??t?{^????H?)?Ow???Y??? Yd???e?2Q????Y?9??_??????:???CZ2?n??L???5??,M4m??Z ?muk??{???D? ???Z????????A7?????|?Q?e???%??? V????y e?????????,?,??lY?9? ????5<??M?p?_O ?????z??J>/Y!??B????XoI???R?'???F?7z?7?p????V2L??>+?J??????I87???k??}?eM?dpe???/e?po???DjK?!????= ?os?7to` ?G?+??s>? <}??HK?d?w?a?%??U?F?^???5;z3?yP^?r ?V?=? \??G??r`E?#?????>w??H;?S?b????????=,Y?UN????VMX??g???=D?jKp=?B??PMD?*k?D??X??'?k??L?;????}mi???7??x%?EVy??}?G???????v??kt??(?p?b?7???p ?[Ew?s????????????/??w?J?????Ynd??o%???J???)?????/???/?W +0????\????????+n(?k?D-??Q???_{???W?"??[?5 ??T7pm??V???m? ??????5???u????? ?]?drb?t?0???>????5?{q?P?hw?*??????R????k????|)??[?J?us???)????oP&E?J??_???\?b#?[\q??5~3??W??????n&???bR???????w?X ????[CKm ?,~??4??!?ksJ!??????'/G??n??G??H%???;?xz?,\??????@??W???e?{?9?b:?zkqNB?V?`?????M??z{,vA?~?3(Tn?gXh;? ?i??8 E??ef?????w?A?`C?;}.z4Q??|?O7??6/???? ?t~g?F??????6???i?@??c??????A?6??P{??*?q???Z ??P?O.?h3?^?L?a$.? A? +???K??Aw[???s?"?WJ??Q?????$O?????^?%?#??r? ?{???????H`&t?8Pv0BqX?4?!E? o)gg???i?r?###??4? ?'k??u.?.??Fr?q???????G?M~?????? ??????'? +'?????;}??|????g?p???7F???I?2??7?o???! ??:???f??????sq?|$7?at7?tUbw??niM?Q% _?pa? ?X??(}?"?lg?2d??????St?e????`G#??1??????Y]??(5?q#e??;&:`????7??q?? }??_V??endstream +endobj +380 0 obj << +/Type /Page +/Contents 381 0 R +/Resources 379 0 R +/MediaBox [0 0 595.2757 841.8898] +/Parent 345 0 R +/Annots [ 383 0 R 385 0 R 386 0 R ] +>> endobj +383 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [105.602 750.9806 118.6329 766.9208] +/Subtype /Link +/A << /S /GoTo /D (page.47) >> +>> endobj +385 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[0 1 0] +/Rect [451.74 342.4254 469.1944 351.9595] +/Subtype /Link +/A << /S /GoTo /D (cite.SLP) >> +>> endobj +386 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [120.6453 310.794 172.7792 322.0716] +/Subtype /Link +/A << /S /GoTo /D (coroutines) >> +>> endobj +382 0 obj << +/D [380 0 R /XYZ 74.4095 738.0292 null] +>> endobj +384 0 obj << +/D [380 0 R /XYZ 74.4095 473.7055 null] +>> endobj +66 0 obj << +/D [380 0 R /XYZ 74.4095 463.9646 null] +>> endobj +387 0 obj << +/D [380 0 R /XYZ 74.4095 238.0145 null] +>> endobj +388 0 obj << +/D [380 0 R /XYZ 74.4095 132.2611 null] +>> endobj +389 0 obj << +/D [380 0 R /XYZ 74.4095 113.3072 null] +>> endobj +379 0 obj << +/Font << /F26 180 0 R /F31 192 0 R /F36 312 0 R /F34 291 0 R >> +/XObject << /Im1 171 0 R >> +/ProcSet [ /PDF /Text /ImageC /ImageI ] +>> endobj +393 0 obj << +/Length 2304 +/Filter /FlateDecode +>> +stream +x?????8??_!`_d fHQg?0?If3? z&?2H??Zb?Bd???t??[?*????]h???u??< ??%?ey?N? ??+???a???b?????~???|?? +?????R)t??8?R?V~??.w??.H??Z&B???t???????m????q~????Uw|A??[-?s?tu??E~_? m???L?w?????|????,a@???Y?$??J!I??a7o?G???E????D??b???u?3??3+???9?5?B?[?(G???W??u?\??????j??)????`?4S/R??R??Z???"I??y_=)B8??B????u?????t?/????????????I*?@i?+*?3???K????ei?=?A???7a?0?x??|?L4g?u??# ?-?, +?qs??N?-??BF?7?????ca????????????eB?X-Y????:h?M??=M???i???8?Mcj???L?1 "???~?????tG?????? N?8???a??Y8?f_3? ~F^*?(u?"?o * +?y???6 g??{??yu????:??l??$I?????dA????8??(Pn?Wr?B?J?K V `*D?a??z?J???~:Thh???f??6Cb-????????? ???kst%+?X???BDg?gET?????w???A????`1??xW???-???N??D??;???-????Aw?/????<?Y/????]??m?&2??c??{ ???]???u?w?U'?>????OC_h_??f???>7???/?Zsa??B??*?g%{????J?,??J6wc>?????3???b?I???????????Mn3R??Md????fU?L+??ht ???w??9?$H? +;x?M? ?6????? ?e?????i??>nF?')???0??{d?U??VLX? +;T2???????:???fG??b?p? ?????c?????zNs??` M?~????9w??m?s4?M?S[????`0/????Kb?*?r-?4S????i??????p???iwa??c????&????V{?3?]C{D'/??@?q?????? ?? %???w???Q`?3H?93??i??;???#????k ,????JA_*{?0??N|???d???t??%? 1?T*??? l??/?RB?????V?c??a??h????????????Y?????p?1???)? +? MU?5V+??mS? ???P?8V??{Q?'/?3!3??`?z??c?? +??s??ZJB????(U????Cz5??i!???O=???FY?(eE.????.?%???X]%sc???[hp?>Eg2?l8??~??7?????j??????#??TV?3?x?w?????endstream +endobj +392 0 obj << +/Type /Page +/Contents 393 0 R +/Resources 391 0 R +/MediaBox [0 0 595.2757 841.8898] +/Parent 345 0 R +/Annots [ 395 0 R ] +>> endobj +395 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [105.602 750.9806 118.6329 766.9208] +/Subtype /Link +/A << /S /GoTo /D (page.47) >> +>> endobj +394 0 obj << +/D [392 0 R /XYZ 74.4095 738.0292 null] +>> endobj +396 0 obj << +/D [392 0 R /XYZ 74.4095 720.0964 null] +>> endobj +397 0 obj << +/D [392 0 R /XYZ 74.4095 608.6072 null] +>> endobj +398 0 obj << +/D [392 0 R /XYZ 74.4095 228.1041 null] +>> endobj +70 0 obj << +/D [392 0 R /XYZ 74.4095 210.3931 null] +>> endobj +391 0 obj << +/Font << /F26 180 0 R /F31 192 0 R /F36 312 0 R >> +/XObject << /Im1 171 0 R >> +/ProcSet [ /PDF /Text /ImageC /ImageI ] +>> endobj +401 0 obj << +/Length 3108 +/Filter /FlateDecode +>> +stream +x??Z[??F~????>D?????[}h?;P M?MQ??:????k?I?_???,??&?E?????p???????Z?6?Q?R??????;?N;?y3?? ?O 3L?]?????* ????g??>???j??s>??UY???X?:???V66?1Q?$a?e?[???B ?fIj<??w??<]E?????Z}???|???z?fa???s?????h???E?-???;??????+&?H???+???W?[??? vx?P????W?/???KZ? ???x?*????r*??8 ???M????????-l~b?;W??n???k?Q@?(x?????U?e????U??# +k?i?Bx??????6???? \??u?I???P? ]?N~h??????-?????_ =??!G??{?c??*D?2?B?nY?I6,?)W?????]*?K????? ?pd&u?:?eh??Q?`K?B{?]??HO5??"*?8????????4?%?A???????????,??b???j???b??uI=????=?5@?f9/ +??&?d?r????f?????m?t?0 ????D?????&I3?J??]A?[q???l?gp:?+?? j?05?;??3??6???6I2??y??????8Jn????0??"??j?N?d`2??F]???9u?A?\?s^??M?tN??$?E?_'??!Lb?Y????I???]?-v8?p ?%??0~? ??]??!???e???B???/tz?b???":?;????#?8Q??+2?UM?AR3a[un??q?Q;,??@ ?g???8n??????vOh?~h?^?C??.??z???'L???,?'?leH ~]/'?`?J??`???G?B?`c???"3Q?) ??xF???4??? ?6???0????#?O?,# P??R?W1???B? ?l???u?f0? +???z?????w?M?A?Htnv??;E/^??[N?[??A??????B|????????kH??.o?H??jz?? +Q??????R?E +?r4?o?.???"k?????|$??+N^Gl???8-??Mf?D?.G ? ?/????????W?$??????]?R<>?]???7Ib??m?w%h?w?????F?JQ???$V94??? 1?~??????F?????%??,$b?????????e7?W??8?Y???5?b *?????#%???? +?[h?|????U2I|i?vV?4? +?B??*3?xg=?o?n_|???????5??p??Ny???3?f?`?Oi??a??x?IWQi????P??~?92?HJ .???{?M?s*q??C???w3????'??1dr?!?G,  9?h??&gZ?(?????????N}?v?K???Z???y??????xcs>???$????wC?#3G?>????0?Ab??f?????v;s??rV? ???FY?/a??3C???n?,???6?0Z?qll[?1?u??????I"t???t(D???s&^0t?k?6a?";?!?????????r???|jdy??'?(???,5????6??i?U??> endobj +403 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [105.602 750.9806 118.6329 766.9208] +/Subtype /Link +/A << /S /GoTo /D (page.47) >> +>> endobj +404 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [226.4163 365.6548 297.1908 377.1516] +/Subtype /Link +/A << /S /GoTo /D (resume-points) >> +>> endobj +402 0 obj << +/D [400 0 R /XYZ 74.4095 738.0292 null] +>> endobj +347 0 obj << +/D [400 0 R /XYZ 74.4095 684.1563 null] +>> endobj +74 0 obj << +/D [400 0 R /XYZ 74.4095 666.5717 null] +>> endobj +405 0 obj << +/D [400 0 R /XYZ 74.4095 287.4744 null] +>> endobj +399 0 obj << +/Font << /F26 180 0 R /F31 192 0 R /F36 312 0 R /F34 291 0 R >> +/XObject << /Im1 171 0 R >> +/ProcSet [ /PDF /Text /ImageC /ImageI ] +>> endobj +409 0 obj << +/Length 2244 +/Filter /FlateDecode +>> +stream +x??Y?s???_?^,?Y? ?N????M?rW??rsS?? E*"??}w?K???|??????b?? Z-%??eb??Y?L?TH??e~X????m??g?1m?\?Y?x??R??7?e*E?&??f"V +h?_V??=?7:??72??z?d??4????+O??p?N?,}Y4?k???#?:??)?z????h?Us?y???????H-3?Yp?????Df?$???dU??w???????"?R?L?X?6???q?t???[?'3YKi?^?8Q$S?cE???-?.?0pn&p ???q?LF?Jv????M??i????6Q??L??+*?3 +???*?[x??AY/?? ?? ? c?01?S?????? :?XK?Z?g28?? f????V`*????>??????e,]????? ?V?U??)l*?%????S2 +??????hZwjiy:WUQ??C???@s???|?M)??1??7????|??}??{t??c?mD&? i2????????? R?6??????ynZ?!c??u?Z???????vz??+*z:?????D??????:????~? ???????'?e?????\?0??dv???uU>??X??%?4g??j ?Hb??*?sf?+p????UK?eq(ZX?V??a?}?????\?_?u???cY???)J???B???1?_ 5?0??qb?&?h???I?dG,?;W9b??):t??J-t???~?P?????Na ?rd3?D???????B?|???o???I?????54???RO ???h????z\?|???P7?8cV????T?*?Qm?.U?Vc ?hL??5??+????Sf???>?[2r?%!a?6?"?p?c???"~=???~[< ????R3?MqWa?#i?[z? ???Q?Lm?L??t`W??&????-`!Av?y}MD????NW??D??? ???!????????:I????XK]?F]??K? ?Y??I!??I??7{?????g?Jm??}Xl????y??????M?X???'i?+?8???}??D??e0?6?{l8Q ?????yY7?s????I?,?B:G2?0TDj?????6?W-m??#??.T%."??H???H?Y????w|?????]I?v??^????????R?r????5Db?7???SX`???R?`?J5???^jC??Z???Iu?z.C0?Fz8?0???[Rk???r??vt??.?x?hI?u?F??SE3{?[5~K??0)??'gi????Zf??i?????%bhfH??C????r? ,JWo J??*P??eht?? ??G??D??o?\????????1?<,h?b?)Q??S?^z?M1?????m7?BY??D???v???qZ@*??h(?-?A0??sQLb?X????3\R?]^?????a??? Kt3J"@??l?*~???????? ?????E??`?;??? ?P??P82Az?3 f~????q?Z?????c?K?+?+??p?P??R)ChI???}]]?FG??x"???d~JO ??adT???K|u(?+?g?z???H./??3/P???C,?Q| :????1 at x7??'?OwB?o?#?)`|?} 8??Te?????$?H??q?: c?#2dd3 ?\?~?z? +???G?p?/?????????t?h=?( %??)HG?_L?I`&X`c8u???n???????/q??Ll;??;@????HO?-??(?b???C?-0;???u??T&Y? ?e??g???"IL?????4J??<?????[?j???/??Zs?,??W?????????O???rr?@?:lm(B +?3?;K??H?? Cg8.???????a??\^1??^ ?b???f?S?&?e???? +?g?\]>%w? ??T;endstream +endobj +408 0 obj << +/Type /Page +/Contents 409 0 R +/Resources 407 0 R +/MediaBox [0 0 595.2757 841.8898] +/Parent 406 0 R +/Annots [ 411 0 R ] +>> endobj +411 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [105.602 750.9806 118.6329 766.9208] +/Subtype /Link +/A << /S /GoTo /D (page.47) >> +>> endobj +410 0 obj << +/D [408 0 R /XYZ 74.4095 738.0292 null] +>> endobj +412 0 obj << +/D [408 0 R /XYZ 74.4095 223.9665 null] +>> endobj +407 0 obj << +/Font << /F26 180 0 R /F31 192 0 R /F36 312 0 R /F34 291 0 R >> +/XObject << /Im1 171 0 R >> +/ProcSet [ /PDF /Text /ImageC /ImageI ] +>> endobj +415 0 obj << +/Length 3433 +/Filter /FlateDecode +>> +stream +x??]????}??*k?DR_ ??lz? P??.??\p?e???,9+){???|Q????=Q??p8?C9?D?/?d&4Q?l2???*??:?E?#????g??v>??Ow?T??M?M?6O??< +u????8???????u?Sy?ea??v?M??????????q\??Mc????3?i????l?????`???'~?/???oO????????&??.?aa???W1,???{F???=M???4L?\m?$ ?T'|v?z9 +??=)L?;?a??[??????ga???f??OX?o?7?p?{>?O????}??8?????+??P?(:i?????6?o???? a?c???.6/?#|?p?7?uw??m~?O??<,T??\E'?#Z??o??g??,????+*"? 0???1ih8?@????4?YZ?&?DEa??j??B??!???????j'???n?c{?^?;???????M???3????A???qw?P???????=??g)?C9XG?& ?:F?? ????? ?g??<[rr?8,??}?u??#????q?H?ek????'?4u?5??u{? ????????]????0?[??(R$?8???D~?? z??Fuoa+0.?g??LO +?c[qx????A????Q?$???0???I$&>i?????#?n&?`i'???  ??1t??k? ??????????Y-x??OJ? gi(b?!??Ztb?4)D??RVT??0?t???16??e??< s ?????$i0?>??J2!3?[???N???'???SZ3???LF???+C^Qz??g\?, at W% ???&???)-??5VI ????8??Z?/?????-?x?< ??e????g8?V9??Cx`????_??XO??'?faV$?(??????~??)J"??W !:5?Sl?.????????+??????n?]? @A4Z/?? ????M?L @????o?BL?X??$I????l?`?*D ???s?k??????"@;^???k?t????\3?BU????????#?+?T??i??t??p???XZD??+[R(b???'??E????z?~{?~_?M%??$???9dH??{?S?? +,:@K|??CG0:N? ;?@??????X?!/? +1?g?V?p6?< ???Md ????^??T? .0???4???zY# ??&???a?4u??????q}?W??'???j?Y??(~????q??9???b+??X}??s??:](Ax?t?Q???\?^?D?????e.?k?UY?? g??[????+?p?C:N!$0????"?/???S??=?+?????a?@z??0?|?>~??G9???bC?.avi???L?^?Z?u??4?????? ?????@n|??L_???4T?IF_vp???+"+97u?A??????H??O???8?x?6?,??L????bne???? O?0wf?k?? ?S?m?k_kg?.? p2?? z??\i??Wq8yS?APg???e??\E>??????W.?????????????Y?,??^!?V{? Sd?????"?Rvi??c?a^?K?L??OE?_-??.[m??????.????e8?v??)n,?D*?? oa??&?t?~??(?;&m??, _???z???+? 8???n?????D?j?_L??P( +???[e?e???? ?????~??7?Uq??O7?R??MWS?bS8s?(??? dY??&]e N?B??7z ???@R?)???F????p???0i?}?>$??????L` ??Fm??1???G?E? ??4L??/???????:??endstream +endobj +414 0 obj << +/Type /Page +/Contents 415 0 R +/Resources 413 0 R +/MediaBox [0 0 595.2757 841.8898] +/Parent 406 0 R +/Annots [ 417 0 R ] +>> endobj +417 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [105.602 750.9806 118.6329 766.9208] +/Subtype /Link +/A << /S /GoTo /D (page.47) >> +>> endobj +416 0 obj << +/D [414 0 R /XYZ 74.4095 738.0292 null] +>> endobj +418 0 obj << +/D [414 0 R /XYZ 74.4095 636.5548 null] +>> endobj +78 0 obj << +/D [414 0 R /XYZ 74.4095 618.975 null] +>> endobj +413 0 obj << +/Font << /F26 180 0 R /F31 192 0 R /F34 291 0 R /F36 312 0 R /F14 259 0 R >> +/XObject << /Im1 171 0 R >> +/ProcSet [ /PDF /Text /ImageC /ImageI ] +>> endobj +421 0 obj << +/Length 2787 +/Filter /FlateDecode +>> +stream +x???????}?B@J+?\x5???? H??[?@?4+K????Z???)??:- +???3g?m?mFz???^?Q?<^?6 ???bs?S????N ??GZ???{?{xg???B%f????Th??&yk ??o?????re2|??P?Y?l????,? +/~?qq*??U???3?qiUp*j_?U?eS?????6?_?????;?y?' ?+m???KB??????k? +??q_z?2???Y?????7??????0??C????+?-?c??\H??o??s??\?'?JE?zh?]??>DS5??, ?b`w:-???muf? +??.???Q at W?U@??S??a?????T??C +:??ff0?ny??G??y??1 ?`Y??????jY?d??????2????j?Hzc?6hX?rW?p$???U??*]Ni??2t!?n??e+'{,?n8M????????zL?Eh??w5o?eB?????`???t??????? ?%?n;(4H??????fO^Xm?PdN??a??M'? K?wU????W??L??J?}??(??7??7 ???,??? ab?J????????B???{?T?owj>5?O eTJ$??@?U4I.???????4?L-P +???????3?&?1c{???y???%???;???5l?nKJ_F???5n?b$bn? +b?]s5??P??r?37?0?]?r??????????????g?#8??Xy?&?Lv???9??#GA8??? ?? ?? ??F"+?????y?"???9??????1R?3N?P?c???? ?????y(????L?i??s?98!??F?? +?e?~?I??#n??J????????v???|H?=c?????????d?U3?}jC???)?)??Y?'?bachR?6?~ +???]????|?y??4?Oqj?? M?????I??????H??|???D(?????a???{IS???(R!_'=5M:O???7xE??????yz??rBZ?f?jxf??"e72??L\??P?XC?)?????????7k?gE?J-'"???@?? g? M??????G?ut????RCm?????P0?5??V?~?NL?? (F#y?A??ov?y????1?5EC?n??r-E??U???????A^???? ?? ?? @?} 7``Th??{i??m?{?wUU??>{M:1?D???O??s???K??Q?}?l????YB??u?B??????_}%???????H4???Q?D~y???kH?b???6_\Lt?^??C?? "?v'??????Q&f?????w????D?5endstream +endobj +420 0 obj << +/Type /Page +/Contents 421 0 R +/Resources 419 0 R +/MediaBox [0 0 595.2757 841.8898] +/Parent 406 0 R +/Annots [ 423 0 R ] +>> endobj +423 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [105.602 750.9806 118.6329 766.9208] +/Subtype /Link +/A << /S /GoTo /D (page.47) >> +>> endobj +422 0 obj << +/D [420 0 R /XYZ 74.4095 738.0292 null] +>> endobj +424 0 obj << +/D [420 0 R /XYZ 74.4095 584.6968 null] +>> endobj +371 0 obj << +/D [420 0 R /XYZ 74.4095 269.728 null] +>> endobj +82 0 obj << +/D [420 0 R /XYZ 74.4095 252.017 null] +>> endobj +419 0 obj << +/Font << /F26 180 0 R /F31 192 0 R /F14 259 0 R /F36 312 0 R /F34 291 0 R >> +/XObject << /Im1 171 0 R >> +/ProcSet [ /PDF /Text /ImageC /ImageI ] +>> endobj +427 0 obj << +/Length 1424 +/Filter /FlateDecode +>> +stream +x??Wmo?6??_!t"1K??^ +????? +lH????"??Kr%?Y???H?5???0D??~??N???cN ???t?E??+?dp???Y?MG?S?r?z???&?????? ???d ??{??????? ?{C???7\??q??_?u?9??u\?????Mqmv????u\6?x??n?W?9??9??m?w?~???H??1`u6??H?V?q`??!???]??>?Q?9??D?\????,???(???1?????r?????s???????????4?zm??Q?*Um???????*!9??? ?'A +T?|v(?7???k8??b"2??v?o+?sS?>??O?7<I?1~E?I?????N +?\??P:/??"?Z??'B?kvg??k5??j?? J?????s?("??`?8u ?????????? ?????L??1?ou?U?K%???Y:z?*??4??j???Gi??L!?{%AL%?`?45??*?Y?GL{c^??>??)ZkVWh??YB:????????*S4*G??t?"?? 9?C?La???>?XG???$????A??`??*?$?e???f?y???????y?"????$U????F`?(???l)t??M??"FKc?H??`??g?m?R?8?j5?2?8a'??????,??:~????v?%??7 >??e?%s??c;?wQ?KH???!}????J?*]?4>KY9g?????$??Y????????"]H]??c]?#????????F?$d~&KQ?\n?M?HP?????@?? ?????????;?8???^  R???a???~??V??H s??$.J<1,o? ?e???1???-??7?4?ow,;K?z?+_???L???%?A????y??|???????j?*~Vq?=?-?????{]???vM;4?y??????:k???0I9?:?$?_?f?????!?h?(?I???????S?'????'#2\??^??^??^??W?)?T??`???l??g??FYs??9?=|?????k/?P6E?V?o?????%d?MF?3M?W???E??,$!??T?> endobj +429 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [105.602 750.9806 118.6329 766.9208] +/Subtype /Link +/A << /S /GoTo /D (page.47) >> +>> endobj +428 0 obj << +/D [426 0 R /XYZ 74.4095 738.0292 null] +>> endobj +425 0 obj << +/Font << /F26 180 0 R /F31 192 0 R /F36 312 0 R >> +/XObject << /Im1 171 0 R >> +/ProcSet [ /PDF /Text /ImageC /ImageI ] +>> endobj +432 0 obj << +/Length 2677 +/Filter /FlateDecode +>> +stream +x??Y[??6~??0?/?"fx????"?n +,???(?"?e??F?K????;?!e???IP?)r87~s!??s?O?S?4?f???qi?P??#???F???{?????&I?????`???V ??????iP:.{??????Xi????K???6Pj?a?G?k? ? ?]\??????k +?yC?????8E?\G?????]K[2??????????&??a?;r??S| ??C?????Zp????? ???,?/?=?s??x???Rvq?b??R,?u?j??? ;????l?yq?nl?,????y?k8)#28)?????_4?<>????_?.?3'?>w?DX at Zo?O+J%???1E~ H?a???a??iPr?:?!????P???K?X??D?\Y??.?1#(+Wo?????SJ?~?B???8??,?u????i??P{>???wo?L???5?jO?q~E)'U?/???C?AK?cU??}?? ?AS?A(???A?e?WG??d@?????????Bw???O??-????@)1TP?W?*???? q??)O??? ?Uf?c?K?C? c?0??B?EC??t???bQ????%?C?q??[?iq???M??h??+??x$?)?C?U ???d?!?l"z$??4??????b?=????B?(}??Z????TE??k:??}???5U????SM??H46????+?B??p?i0|??n??mPci?? ???[????D???h??q??(?? +Y??5? ??&?A }?6????????h?U???????H?RV?9??Pt?fC?"?.??;b???>?m???????? ?n????K?p?+??S)]&???C?v???`??K?p?R~?a??2??E??4???Q9D3A*?t???????~!U???j?`^ ? Z???e????????? ????Z?7????O ?"'??:?2wXJV???Q??f5?q?+D????f?8??B)???? ?qh?w?u?f?l????]?p!????8?mFJ?q????#1qI?}Rn??>??[L?#?jE>???f??????R?p0??????!??r??w;L]?Wv???*????????#l# bo7H@??p?3X???8v?????#5?????? W?:Z??`?~?? 4(?|"P?????XA???/?m???5 bU ?>????q???????{]?7d9?M^i=?z?F?zp ??_????]j?? ?6?????Z??;?y???T?????S? ?? ?T????????Z ??\?$?q?kJ8??y?d??\?=??????=??]S?*?lzu????;>??mMt}>,?i at V?3w at 1??^?????j +???=??l'??? L??'???+??%??X???c???pH????w6??7?????? ????1??????5 (?????????P?:r??1????kz???W???0v?ln???kd??0|??d??zX?3???Xx??"*??v>?))|?3j?gPe*X???u?????j?@8???"'??o?W"?>?;??? =? ]W??FJ0KL-??{iR? P??????o????? ?B!???6?1?????=?a]\z??K?-? ??G[?R at u{"?L!?4?,??FO5??? +????p>~??po_x??w ^p??a ?????R U7???|YJ??yw???8??2$??w??(y????i?:???3?r7???N????}?;?F???[?!?N?I',??X??yp??????endstream +endobj +431 0 obj << +/Type /Page +/Contents 432 0 R +/Resources 430 0 R +/MediaBox [0 0 595.2757 841.8898] +/Parent 406 0 R +/Annots [ 434 0 R ] +>> endobj +434 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [105.602 750.9806 118.6329 766.9208] +/Subtype /Link +/A << /S /GoTo /D (page.47) >> +>> endobj +433 0 obj << +/D [431 0 R /XYZ 74.4095 738.0292 null] +>> endobj +430 0 obj << +/Font << /F26 180 0 R /F31 192 0 R /F36 312 0 R /F34 291 0 R >> +/XObject << /Im1 171 0 R >> +/ProcSet [ /PDF /Text /ImageC /ImageI ] +>> endobj +437 0 obj << +/Length 3297 +/Filter /FlateDecode +>> +stream +x??[Y???~?_??h?U???oNk????` ????-??H????T??kDj?&?`$????_W}u??lE??le$?????P??j{???Gx???l??M?_?n?????DH?Ww+K???jGc0??y??????n?????!?????f?]V???[N?yx?=?g?l???E}xF?n]????g??n?? ??????o????o[9?4?t?a?8i???+X`??z??7?k???&?Y?2J?? +g?G??8???????????r?4/?g?h??h????Y?v}! w}?u????)?b*sJ??T?A-???X+q??+J$?M?Y?{x?? ?.,g4 ~???V_W7???~?N#?%?3?r?)??_???t???{ rV????9???FJM???????O7???S?????j?/0x???l%??:?{??tR?u????mu8Vu????`4?????Sv??}????/TQ??@[? UR?5??? +?E???a?,^?H?|F?F???mv?=0?!l????}??w='A?[????r?`?`w??#N?????????l???? ?_ 8?????R?m?????? ?????&?XO[???E??]? f??s?2????,??J?????OYS??M?!e??????;C(3,??yA??y??@???:\?????#??????!=?? ??s??s???|?)?h-???0????f????u_?????uvH??.??`)P???S??L??????? ???h??`"??????jw?????C ???Hy??uvx??0?F?|???Z?mvY??K{???@:????kp?p?x~?~??p????.U??AkBI??2C?A??*w_?#m +6??dT\?\%?????^!?j??Z_??4?6????U?~.????SH x??+???G???l ?!?B???????p?m??p??a?o??1*?T???C?X??([l?.f/ :R?3?????>?T? 0?9?|q?^?1Ub???[k??:? 8????`?D]c?ji_???!??d?4???8?C+????V?Qwx ?'??0???A}?/?E????? ?D?6?Y????|j??f?r??kM? +{??!R???ge=???Q????0???RM?=B????RE???v???{W??az? S?}e`??Mz????.8_?}H[E?]???T?x !2???U?.??? ?`I????? 4?"??q?????0x ;?._?G.Sq]??Y?=???.v?6Q?X!?l_=[?????!???&l]f????rp?????????#M~8??l?G=?I?Jt?~???B??/1?G??r5"F7??)te>eS4R???k?_?b?Y??>|.P????????{_|??? v ?!e?MT?q?X???????6N??????/x?:L??X???????>.+?K??UT??G?O?]?c!??DU???????3???-?W???!W?]?P%??}w??????=????*\??}?8??H??_5??((;7U??b??f??`??D?????#?t> ??H?hh?=xh???|B?c?[/???|:???t|5??&\????T +???u'?`qM??????4^?????????????????`&?f?Y CU????6\? C?w??|{n?'?Y??s??@?/?&?p??w)? ^? ???z%???p????4?_p?E? ??-???(?????9??c?b??C?WP??P??v?l\@?s? ???/P??W???NQsU?`pk???g?.i??,\vy? ?(?q&?z?DS?0sz7?Q? {?`???I? p??Nt???????????/??`??^?c7?(Z?????,q????SI?\?P%??????O?!r?~/????;??T?]c?r????L????!??s?sxK??}&*Gh?0?mTm???\?????x??B??? ??_]W??B8???????5!{? O?? +????^????j?????YOM?u?Oh~~??P{??31?iY?K8?????????\??d?(?? ?y???`?E?h|??"???q??QR??X?5?f?L??-??)?.????swUe???7?K ???U??(?4??z?7AnA|?, ??O? I?5:)????q?? ZX"!R??????ea?g???(?@? ??b??6??6? +?-3}RE??F??3??f ???m,b??i?s? ?Z *3p?O????8+G_0>oU?Jb +?4?????x?V Em?Ca?M?"????4S?44?????????'??&?k?J?U????????' +?`>?Z2??E&???E?V6N!?zj|j ? ?X??I??S; ??????????-o?s??/??Z1???`\Y???}??h???gJ+?}T?F???Q???j???N;dO??C?s?Y??C?jb???,??s?y????A???????M_4??{?%??;??o'm1??l????e??] a??Y?-u?-???b_7s???^?. +?&4?|??=q?qwbK?>B /?&?r;??cl?;i?4}??????"?H}?? ????{b??}qK?wb???&?M?wA?-?`L???v?? ?|????????YExlx? }{???,???=?"?4{????wb??F??????M^m??Z?? ??? ???aoO?b???????P????????[?A???aA?????'??J?y?9f??I[??s[???????????[?!:1M?? ?n? +??/??mLr??????nO?b????????u?4y????wcK?? e??]???/?????\?/7?????v??=q??wb??>B?lz???a??;????????r _7?#?u?? HZ?/????-??Y?-?!?????0v???????k????W?_??RL\??s? ????i???-??Y???}|?????l?;01??????e?!????FZ?7???Dx?=?#???????1??endstream +endobj +436 0 obj << +/Type /Page +/Contents 437 0 R +/Resources 435 0 R +/MediaBox [0 0 595.2757 841.8898] +/Parent 442 0 R +/Annots [ 439 0 R 440 0 R ] +>> endobj +439 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [105.602 750.9806 118.6329 766.9208] +/Subtype /Link +/A << /S /GoTo /D (page.47) >> +>> endobj +440 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [132.3743 390.4952 235.5173 401.7727] +/Subtype /Link +/A << /S /GoTo /D (performance-impact) >> +>> endobj +438 0 obj << +/D [436 0 R /XYZ 74.4095 738.0292 null] +>> endobj +370 0 obj << +/D [436 0 R /XYZ 74.4095 464.9782 null] +>> endobj +86 0 obj << +/D [436 0 R /XYZ 74.4095 447.2672 null] +>> endobj +441 0 obj << +/D [436 0 R /XYZ 74.4095 303.5711 null] +>> endobj +435 0 obj << +/Font << /F26 180 0 R /F31 192 0 R /F36 312 0 R /F34 291 0 R >> +/XObject << /Im1 171 0 R >> +/ProcSet [ /PDF /Text /ImageC /ImageI ] +>> endobj +445 0 obj << +/Length 3152 +/Filter /FlateDecode +>> +stream +x??\]o?8}???? ?,???m??,:?]tv?X,:}p%1j????L??\??H????n`jE"/???9??K? ?d?8????baj?d????[x?? R??7??q?7???rB8b\????Dc???? A???8????q6?O?a??_fs??????Z}?Q<-???z??X???????w/g Oe?^??b?[mK????}??U?O???????AF?'s???J???? +JM?7????.[??HM'J$$?w????.??( +m?y\?????????Q?D!??:h? ?m??V???V_y???bsU???(?uQ?_????f????@???f??????\??`??~??n7? g*???u? ????JT?5?g?$?^???????V?MQ?*???wt_??????\??w??????|??qw???????WmM?\Xi???????bQ?j?????|B]_H?5"??????.?|Gd?* ?a>??v??DR? ??????#/ +1EY]??????c??|???O???5??U?X??????^n?W#??&bz?]?????Rw{??-?3(??UL?l(#?%Q?uPr??0????X?DX?A)N?,#?s??B???*$x?n"??`,?R??b?0zi??,??b)??aS ??1"X +c?W#?+?:??9? $ ??3?(?,???e#Xa`X ??H0,??bI??c????G6???(?P*5???(??f?D%???F#-?5L??Z.???4?@$p=?X??2?,???Y????i9?e?YeK?C?R?,'?s????=????B`?L?,??ecY``Y??D?0????H?H???+??"?2?Xd?X ??|?bA?3?`? +?-???sBw??Xd-???b????X0?C?,?2?,F /e?sD`Y6???(?:(E?wy?fQ?3?E?J2B3&?PU??Yd.???b?T ?X1fC?,?2??I?3??eC?,?2???d?k?Z?qY?my??/?,??? ?A?t_-n??"?&dz??$?{(y????!L????>??Z?????D?????n?????RL????&G?a?"B8???!%?>!???mS&????q???)E??r?0U????\??U????;??'?hw??????Jr??????V +?\c???g????k??????5? ??}o???;???????bs?{??jz?/????}?m????9??????(?#=V??Q?m} ????[?Y/????>MZn?7??=<8?.1?S7??>9?A?! ?* 1????_???'??uH'^}???>W?"I?d???????\?????Z?G.W?Z(?ax??dp???#??l?u??y%#>?<(????????j??8?K?o?#?H??[-?`?.{A??}?G)???=mt(???u?):?A12?t?v'??CzZcL?? +L ??x-N?????7???BX??'?f3???6q?'9?5/7C9\a???GX5?Q?Y???x?O? ?} ??????? ??????g?:??????????????D?EM?@?%hE?`????nL?$?@?$? ?????vO?fDq? K?H?????W.j??.?8 ?H5?"????23H?\?{????T?U5???~?:~?V?kendstream +endobj +444 0 obj << +/Type /Page +/Contents 445 0 R +/Resources 443 0 R +/MediaBox [0 0 595.2757 841.8898] +/Parent 442 0 R +/Annots [ 447 0 R ] +>> endobj +447 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [105.602 750.9806 118.6329 766.9208] +/Subtype /Link +/A << /S /GoTo /D (page.47) >> +>> endobj +446 0 obj << +/D [444 0 R /XYZ 74.4095 738.0292 null] +>> endobj +448 0 obj << +/D [444 0 R /XYZ 74.4095 660.2459 null] +>> endobj +449 0 obj << +/D [444 0 R /XYZ 74.4095 409.9845 null] +>> endobj +443 0 obj << +/Font << /F26 180 0 R /F31 192 0 R /F34 291 0 R >> +/XObject << /Im1 171 0 R >> +/ProcSet [ /PDF /Text /ImageC /ImageI ] +>> endobj +452 0 obj << +/Length 3303 +/Filter /FlateDecode +>> +stream +x?????4???"o??3?X?? o?0?g?x`xplw?m_B?????????7??"?J%??Un? ?Om?? 3?$J? ??M??????Q???H;?????_??Fi??q??????? ?3?(??????i? ???"H|??v???:???6 ??oq???MS5???`??6 +????|?3?X?/?NU1?_??z?e?6???p?D?????t???a?????????,????p???82?v\z<??f????????5]??N??W?Gqrq??g??:??????EUT??z??2? ???6?EA +tb?IS??m~???i?r??????oW??|?????w7????????B??2_?????`S???? ?R?????U???h???????ps?????5&?8?l??????Mc???h?XP???X???x_?dhw,I??+N?FA?.b0?$5?&?2?IB??/{?j?=??a?K??r??^??]NK????pa?Oc?U(x2?g????]??1???Dq6+??????n???PG?L?q_?????~????_??MM? ?vZ`? ????V??%*Y???p????T3???w>7E8?????????5[s $??(??l?h1??"q?D ?????*R??????q?S?;V?P?-?7Z i>?H?qP???8??)bY#?m??vO>??G?W???a=y?&?q?A8????c:??-c??? ??u?5-?~??{?????V?????>?:2?)??L????E +d?p?????8?f????W???%f???a??\?????`???'w?w?0P????]?j^\yp?!9???L???dD?v.?J.?3???L ?1@?? ??H&~?)?????T( Sw?^$????????Quc%?~?'A???tj?"??? 0?? ?B?A5?/n?>???F?sF?NX?7~?-??y??r?i>?? ??????20??i8??C??????zq? ?????L??0?D=??a?Na)?K?>??/=??ET? ??????Bs??v???d?JC??:?&???bC?-???8??#\JL???b????oAs?????????F(I??? ????0??W??????%??3?C-R??fM?! +?fi?7?.??b?? gMH?i ?F?Gs^QNQk{Q??,D????n?L???????3?????%????6D?????qv?h?@U??w?1???.9c?k?????p?Ju???? ??l?d????WM?'?????u??i??Rl????W?CD?6G???p? ??G?[???H??#???Q?c??????F?9??z?1?#? 9 ?%??r???L?JF?G???$?e??cM?N,R ???|?m???}1?,r??XM???&?a??^J?]????m?z P?8T????}?<"F?GAvt???r? ????????h4????1b\???o)??*[??K???Ct}?9?7c?Up?b????Qh0??:?kv??;^o?4?Y?[?YOXil%??S????*R??-3`KYI?a?,z?o????1 a???02??9??=?????%?an????(??&gA???s??o?Q???\ :?;????_9N?\????[?? ? +??uo???=D?A??%JH???{??????i?=V?T?OXlZc????_????1?Y#????<?7??(??????? +t_?x.?De?1G??Br?: ?g2???kV??L?*?Z[z?????????6??]n#???^?R?A6???????S*???l?Q Y7?.????V??d?? y??zj?%???* ???????oq??qx +????????G?x???o~z?^? d?=??n?H?n~???`.???R? \???7?.]?V???80?u??e;????X?&H??v??,%4?i??dj?b?r&q?+?2?R?:?o?????9p>U???&7???J>jV?L?]W??p?)?4?2?3?j???H?o???}?n?????H???n??> endobj +454 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [105.602 750.9806 118.6329 766.9208] +/Subtype /Link +/A << /S /GoTo /D (page.47) >> +>> endobj +455 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [489.7334 629.0379 521.8625 640.5347] +/Subtype /Link +/A << /S /GoTo /D (performance-impact) >> +>> endobj +456 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [73.4132 617.3019 148.1323 628.5795] +/Subtype /Link +/A << /S /GoTo /D (performance-impact) >> +>> endobj +453 0 obj << +/D [451 0 R /XYZ 74.4095 738.0292 null] +>> endobj +457 0 obj << +/D [451 0 R /XYZ 74.4095 498.5273 null] +>> endobj +90 0 obj << +/D [451 0 R /XYZ 74.4095 480.8163 null] +>> endobj +450 0 obj << +/Font << /F26 180 0 R /F31 192 0 R /F34 291 0 R /F14 259 0 R >> +/XObject << /Im1 171 0 R >> +/ProcSet [ /PDF /Text /ImageC /ImageI ] +>> endobj +460 0 obj << +/Length 3853 +/Filter /FlateDecode +>> +stream +x?????6?>_??R?#?x??=?q????8?l???@I ?)?????/?=??????7?6??&?? ?p??t?7??M?9??7Jpvi7?zsw???:?(?????& |??@4J?P);??}x?????$????^mw????Y?ou?? ????1+??,??-??mM?=fUSf?]??E]1?us?m??????~4j??i??M??2~j???? L?c??G????c? ??4??8 ?02!?A?'??8?B??O 6L6??????b}??????3??X?V]P?Uo??o?C~????S? ? ??????? ??q?X\n?e????? ?/7??<]n??wg?y[??v??m8???????R_?pG4???????? HP????x?JA??7?F? ?h2R?|?h??4u??V+? h??O???b??oT???`%c????N8?|?z4????Z????!?\?a?Z?;?a8?6&???59_fS??u???W?e'???~?????U??@?q??????q?Sksz?Z/?+h[mh(;6?<~v??( ?H???c????*?_\v??b?u?O??9?U??#??U?C????????3a}E{F? ??ro??A?5????TF?~??xv*?????R??W?????????mv? ??e??X??^P??????????R????????]???6 ??E??]?7?F`??k?pX??_P#f?@J +???[KS?9G ???/?z?vF+R???Q?e$Nuq?.]?? ?)?e~???? G8??*_?-^B??????d??A?:????5M ?????_ P??{?o??c?? F?l???/??gfA??c1d??????? |????(?(yh"?@ ???o??.??5????wE? X YE:?D???(RA?6 B@??FV??????^|"s>???$???? v-7??:5h[??8??BI??y???5?$6?3??~Y??v=?DG$2??aV??:????li?z=???????~?<2?>_??w?V??u?o???`???T??#??s"???)9qS??????K?V???d?!?????T??K4F.?@9?Q??d?q???`P?]? V8????5 ?j?#?Ou}d????ma??P??? VS?B???8kJ2??4{?????>?????/?8(J???????e??gP?8#?A6???L??y???i?k?eA?B?vbf????`???3 ??(?`] +N?JN??I??m??W?????a??)?? ?m??gLYz]???v?ER)3q9?V????J???;,?FH/???E??-?8?E???? ?1 +?4??I)?e%2?pIy?7?????T: +???:f? ??Y?3????"WRp5My???W??QxV?j{??+9? +?6+??A\??qQ??2k?K?mg???3??4?????7?J??N???/]??*????????O ??"?6?xZ?+?.? q??T?ua??Z36?9 #?????!b) *.???iR????>?id/A?8 4.5.D4????v??F~j5? +???hQ???H??'????k??r? ??A ? +? +7??/e"?i?^3_?(??I??2??:???????@?V?]?L_k??X +?b?? ??*?*???$????hZ???? ???1???f??+?k?S????1e\-?????(?09?D?f???O??D? ?#r???\F??*?R??? ???`??X?? _8u#q$?????CJ????r/\?????Zl???1Ojo?fVdqi??;P2?xM??Z?8?xIG 4??????F??~??g`?c????7A`1????e????????Z????Z'?r!)?S?p??l(%U?????q?????rD?????? ?b ??78?Y- ??x??CN^ ??l* ?6?t?f?]u??iJpTDB/??????m??,?*?q?PPMV +???????0?8??^q??LH)?c??+???3?s?K?3???j???N? +?\??w?????????IA?^=Sye?9?=v&??p;?%?=?z?z?z&_??N??0?l?3?G? ?8 ??h??%?uh?5? ???#?}y?^c???F??\??{U$J?T??FZC????? ?? +G?Dh^T????=E??U??;>?p?#??(fa?Rq?Ms}??}R??5????#????o?|12?6?j??x?zj0?q;??;?????{??0?1???5?ou???C06$ s?????I????-T;,??~\??%?????z??-?PF?s? ????????F???N??8??9B6J???-???g???????"????Z?CZb?=?8?? }?@o?Y?`aS????9??S???"?? ?8?> endobj +462 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [105.602 750.9806 118.6329 766.9208] +/Subtype /Link +/A << /S /GoTo /D (page.47) >> +>> endobj +463 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[0 1 0] +/Rect [314.7955 694.519 341.3756 704.0531] +/Subtype /Link +/A << /S /GoTo /D (cite.SEDA) >> +>> endobj +464 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[0 1 0] +/Rect [361.4198 694.519 397.9225 704.0531] +/Subtype /Link +/A << /S /GoTo /D (cite.Twisted) >> +>> endobj +465 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[0 1 0] +/Rect [364.6959 534.2776 397.0742 543.8117] +/Subtype /Link +/A << /S /GoTo /D (cite.LIMBO) >> +>> endobj +466 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[0 1 0] +/Rect [139.7638 481.9055 221.9351 491.4397] +/Subtype /Link +/A << /S /GoTo /D (cite.von-Behren-et-al) >> +>> endobj +467 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[0 1 0] +/Rect [379.8296 469.9504 419.2216 479.4845] +/Subtype /Link +/A << /S /GoTo /D (cite.Seaside) >> +>> endobj +468 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[0 1 0] +/Rect [429.7417 469.9504 496.919 479.4845] +/Subtype /Link +/A << /S /GoTo /D (cite.PLTWebserver) >> +>> endobj +469 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[0 1 0] +/Rect [76.91 353.2511 112.0578 362.7852] +/Subtype /Link +/A << /S /GoTo /D (cite.AB-OC) >> +>> endobj +473 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[0 1 0] +/Rect [369.2884 87.3642 393.856 96.8984] +/Subtype /Link +/A << /S /GoTo /D (cite.R5RS) >> +>> endobj +461 0 obj << +/D [459 0 R /XYZ 74.4095 738.0292 null] +>> endobj +470 0 obj << +/D [459 0 R /XYZ 74.4095 279.787 null] +>> endobj +471 0 obj << +/D [459 0 R /XYZ 74.4095 217.2331 null] +>> endobj +472 0 obj << +/D [459 0 R /XYZ 74.4095 158.6831 null] +>> endobj +302 0 obj << +/D [459 0 R /XYZ 74.4095 158.6831 null] +>> endobj +94 0 obj << +/D [459 0 R /XYZ 74.4095 141.7522 null] +>> endobj +458 0 obj << +/Font << /F26 180 0 R /F31 192 0 R /F14 259 0 R /F34 291 0 R >> +/XObject << /Im1 171 0 R >> +/ProcSet [ /PDF /Text /ImageC /ImageI ] +>> endobj +484 0 obj << +/Length 3984 +/Filter /FlateDecode +>> +stream +x??ZYo?F~????????O?? ??'??aPJ??CND??????n??-M @?????:??? ?Om?8??"?dQ?????xn???+%4;C?s?~????'?nTDq?7???< ??m[??p|????Q?},??-?w?vl??;~Nu5??n???O??A??b`?f????????d???G?????m?0 ?"??,I?$??;v=>?o?)X??;???l?yqq???? ??l?q?????l??o?M]?????k*?f??rUqQ?0Ody#????0???b?r?????? ?B?????????~???:?&????*?}?J??h????????+??"O6??"U????8 ??&-?????*?? ?4?????????]???6?K&?PA?$???/o>??"?3J???????`f?c????2??hh?%b?b?^?K??L?<?%W???p{]? ??>b?$?????a?/??z^??????=?b?/_????x5]????Jc?^0 ?fy?W? +|^???BrP?u???c??????f*:m$???4 ??2k???>?r?????j?? ?8??!Z3]? ??s? ??????????}???XlA???D/??U]??+i???p)?O??????2m???? C5 0X???????bt"??8????G???|???Q????U=L?a??^???92he?B??H??f?E^}?????ZL?,?*nh?jL?pk????[|3a????+?6-D-|??????xN/???B??.??za?.???L?^??z????o5?\??[?? ? \???_??a??/???7#?t?????(?y?Hk???{}???cS/????,?F?dt?Y??????8????P ?b?S????D?CC?=??????i?1#l Cbt?lR'ul?"???i???db?0????????n +??L4?+?P??x`I??5??@?njZ?,d?)?????wu?u?*?Z????????e?$i$????? (6Ff? ?m|?&s??!?z?2?L?~khKh???????????6v?8?w??l?Kg??()? /Jr?hJk??????:FP??I??0?-??1?@?n?(???LI? ?????~? ?zg???C??X>?d?4?C?Qp?????T,?je?B??kAS\?F?? ??]?+????V???????G8D???F?(??1?,-????O-??S?-??I<6K????)??EO\o?;^??t+S%LL?5?P?7??5??:?7??iy?D?k? ?pN???????~??????A?/`>??]0Tu?%??.,??u?e??k@"??,??????????>?`;J?w?>v???? l.??Fs?ad?????????/?Cb(?S"??Y?6?PA???c????|O?yqQ7?>??A/?/?Q????L? ?-j?H1?*?0$?.Z?Fn?k??}??8?!????qn???|????????Hr?"?1 ?????t??H???|B??9???g??`??dE>?tc??_i)?????lK2? ? +?(????SA???$s GFW ? ????hvD?E/ qv???k?????E?8???????s0??q?h??-??cv??Z?s@?|???:?d?#@????0$?kdp?NZRh?sP@????nYBoR(??? )?+,?Un??? ?????=?)X????u7????IP?????w???c??Cd??#?7,????q????i?l?? ~9:;1 ?V??$??? ??}????K?+7??Y[?????Ci?Kc?9??D[??)?R??j? t??An?]?qit??X???rv?pk/?p??D,IS? ??m??lt?&nS?gy???> pK?N?dW"_/?~?GX????z???H???????Az??i'GF2?/:b?????:???K;?/?I?Y^?z?>??~#F??x.I???? ?? +??+~n/_c?3'????B7r?0?Q}??B V??v?a??]??=i=?/?*??????????????? ?4 ?;?C?;???$+?oD8?:z(???????Xh-??B?????*!?Q8???[???  ???n??:?*???}?P??I^n??? [???????w??Np?#??5Ei?T??R9f?.?E?|???C?????wo??????B0???_?E????Lg?e???> endobj +486 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [105.602 750.9806 118.6329 766.9208] +/Subtype /Link +/A << /S /GoTo /D (page.47) >> +>> endobj +487 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[0 1 0] +/Rect [76.91 697.0778 102.9022 706.612] +/Subtype /Link +/A << /S /GoTo /D (cite.CGSI) >> +>> endobj +488 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[0 1 0] +/Rect [76.91 685.1227 100.3917 694.6568] +/Subtype /Link +/A << /S /GoTo /D (cite.MAS) >> +>> endobj +489 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[0 1 0] +/Rect [104.496 673.1675 138.2489 682.7016] +/Subtype /Link +/A << /S /GoTo /D (cite.PICOIL) >> +>> endobj +490 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[0 1 0] +/Rect [417.0789 673.272 453.4221 682.7016] +/Subtype /Link +/A << /S /GoTo /D (cite.PMTPM) >> +>> endobj +491 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[0 1 0] +/Rect [132.0819 290.6021 149.5363 300.1362] +/Subtype /Link +/A << /S /GoTo /D (cite.SLP) >> +>> endobj +492 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[0 1 0] +/Rect [365.166 117.2522 397.5443 126.7863] +/Subtype /Link +/A << /S /GoTo /D (cite.LIMBO) >> +>> endobj +485 0 obj << +/D [483 0 R /XYZ 74.4095 738.0292 null] +>> endobj +482 0 obj << +/Font << /F26 180 0 R /F31 192 0 R /F14 259 0 R /F36 312 0 R >> +/XObject << /Im1 171 0 R >> +/ProcSet [ /PDF /Text /ImageC /ImageI ] +>> endobj +498 0 obj << +/Length 1565 +/Filter /FlateDecode +>> +stream +x??XK??8 ??W??P?zX~?????h??6??G???4Vvv?????$???,?I?)fD??ODy?R^?(W???Q??x?????2IJ.????^??Y$R??LF????L9(?J????k|?|??Nd??7?|?DT?2g? %B?2?sg^q8???p????6????. ?Z3?)MwG?q?e>_Da?O.?0\9p??H??"g?????Y?'?_Y???V_?????t[s????,9??^?Z1?xz2?E???g)?-uR?k??X??????????? ?O????6*/X)??{?Lh??;??;?vp?+ at PY?? ?D P?Vi??T??UV?O?=?t?M?????*??????|W0??ZS???"?Ik??????1?A h?5??5;6??Y?$??+?_w ??Y????????W???y ??tp?m?L?'?Nc?????)??H?/?_?.?$}?~G??h? +s?:???=5?gU?1??Jn?awj???????{?c?B?aU'T???{lMgz??h ?#???????5???Q?Z?f?l?Auo???? ????Dn:S?z?K7????7|A???Mc?hJ,??hz*??????=?? +?*@????]$??+???????o????!???qi?|?d&?!+y? +??0?^?Z?g?????''6??n0????$bCs={Sy?VC??L?? ??$??G?*?:|g?F? ?^??1??#?L???b????cNa?1??5(????z????*?????;?oX?????P^Ww?8{Wf??@H3?=2?x??8|o?????}h3Zr?1}?1}?U:??=??????mL} ??#.????G?8??LI?? ???U??Du??t$^6w?J +?n????:?l?{????T3?Y?;?32?w?V?????ksu??W?dUyQ at 4?u??Y??d?H2?'>????? ??'iz?@>@?8(?bb????j??????7??`R*?%g???3?$?\?n??.?tB??i????????a V?????I??iMR???~?k?X?T???>xr?T?Ilr`?????yM? ????MB???i??C??p ??E ?x??B?d?m???+??0?V?3??}?8u5?????1?6g%D?????Po=????e6XR?@???U?a"????`?* t?uE???"?????R ???_s7wo?%?T??g?2??9??&???????g? +?T.?u?M_??o?D~^?,??1?>?jH??????0x?D??:?????U?C?-Q??1??????_@???H"????????aP??#? +?l?????GV&?;p??u???` ?endstream +endobj +497 0 obj << +/Type /Page +/Contents 498 0 R +/Resources 496 0 R +/MediaBox [0 0 595.2757 841.8898] +/Parent 442 0 R +/Annots [ 500 0 R 501 0 R 502 0 R ] +>> endobj +500 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [105.602 750.9806 118.6329 766.9208] +/Subtype /Link +/A << /S /GoTo /D (page.47) >> +>> endobj +501 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [450.222 587.5187 521.8625 599.0154] +/Subtype /Link +/A << /S /GoTo /D (composability) >> +>> endobj +502 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[0 1 0] +/Rect [454.4339 547.7427 490.7772 557.1724] +/Subtype /Link +/A << /S /GoTo /D (cite.PMTPM) >> +>> endobj +499 0 obj << +/D [497 0 R /XYZ 74.4095 738.0292 null] +>> endobj +496 0 obj << +/Font << /F26 180 0 R /F31 192 0 R >> +/XObject << /Im1 171 0 R >> +/ProcSet [ /PDF /Text /ImageC /ImageI ] +>> endobj +505 0 obj << +/Length 3464 +/Filter /FlateDecode +>> +stream +x??]o?6???b?N??$R?to??z?A?????????wu?JK?????/??va?f??p8??p?_?3??A??J? ??]~? v'???&??#?O??qw??Q? ??t???wi?????I??a????????}???????o?J??m????(? +F~?w?`????????w?*?l?V?v{]??????y???v??w??p??Y??n*?????*??x?=????n?V$~??????'*??#??$4?&R???$??y?mV???OTb?/d?P???j6\? o?]??C??_a,?(?%W:V?RA +?$?IS?????_??i?????M?3????p?????f???eR??B???0?3??_~ vG??O7?AY?? ?0U??h??:?? ???|3?9???-!?Q??I????9???UH???????????A[VE[??}qi@?:?D??????KQw?z?@?I??|??T???3"???m{-?/M?1??\q????cO??ZA??????Lli??*?????(?? :?"?n??^b??;??$???O?????????V{R??{9????>`?????4?+`??b$????nnC???w??("?H??nd? ??^Uv??3? 4^????1??c?'_?????uo??M7?+?'*R?T?? ??[??{'Wg?a??+?JF??r"?A$?k?p ?#??? ??#T?X!|?? ???")C$??8??6DZ?WI?????$?????pY?? ?A??E ????0? ?????L?:N?*???(H!??RM)`9??>?w^8C)??c:y??)??t32?J??.??k??g&?2?\D??????}8??3>o ???dNg????CpC??[???A?GF?/mn%`???QT???g?F?????vZ???F????P?xw?R&?g??m?v???Xvg? o???XG????? +?l??v??4czxC?>?g;???????\ ??? ??L?????V?}7?u?d?$?s + at bF2?)???????O= +%????>???u",?????O?H?aU= +??????"? ???:j????6%??!|?)?cQ???Y??b???F????,#@t?5q??!??Y}?@2Z+??????y-??U@???+z?F?z$g0:??Z???? M???\7????> C???{%`?>??q????e?? 2*S???~??DS?/?,t??O???????wA?? ?A%i?`a?C T?-?? ????1pS&?????,G?;?y??*???=4a???W^?6????c?@P? +p????????6?B?$?^??R 1?c? ?A????(?Aw??Q???????9?sZ? cE?E >? qC????a?????? ?n?A???SXN??d?dR?L?[??H? :q!>@?rf?y??[*_??\)Gl????c?8^(E(sY?-RJ?P????????Z??????????_???B??$?f?E??m ??????s5/???O?a??w?? |?.?X??????W??y?(???????!?lv.??s????D??=$? k9 +?@8?&E???}]vO?PC%N?%???+.f???1??C?7?1???b?Ra'%?~?}p??2`- +??Q,|\?RAq???????l?.?J??3 +K%???!=n??L???'?D]?F??$?O?OU2n???????-b???????t??:??05?X?#?O??|?bVc?????????e?qT???????>?`?3?q???Ov????cL ???t????\z??9[????NJ2P????????4X at E#?Q???m???mEI? +l???????:??5B?5??Rx?*????A????P3?v?/ ?=??? v??? +????\=?pq+?j?QaE?/m%??????9?:????k???6v~e??????"|?9? Z??h4?Qeb?f?W??+?u?K??S??t&??N?????????,???????????-??P;TO????1zA??6N?J?:g?????z-?&???%u;??????0 +"?v?L??IQI?w??????k??x?P?*X??(?h(??????x?6?q1xV??d???W=Sa"???????`(?????:???V????????? ?\?b)??P?q??n???v? +?? ?>Lx?- ??L??%=0?X$n????jfg?6?2|???8?H??M?l? ??%??????????????>Mr??SQ"+A???g{ +\?[???8??b?r *?>? V?s?@{??ZJ;5X$???=]yo&z??P86??\fl ?j????4T???D?7T?o+?B?{9??]!?XH??J4????=????:t??r??8 ????f?F???**Rn???????q????Q??? +'??K??????3???????;I@^??fsy?6 ??Z?&?>?JS?=s??7?????$9=@???'0iqQH?2????????A???& +????zf*?????? +??? +fP? ?`.????jr?I?4g??N?2I??c?W????F.??2????D>7%?_????]????j|h7??m??????fy??b??m%???Z??h ?O????#?5???R!?J?~???.?Dk,???eN??p2?????7?????5o3?p??p?^QW?G????q???R?J??J?&w?8?'?H?o{ag?$?9A?c???z??k???Eg?#?wa:??h??b???n??nendstream +endobj +504 0 obj << +/Type /Page +/Contents 505 0 R +/Resources 503 0 R +/MediaBox [0 0 595.2757 841.8898] +/Parent 515 0 R +/Annots [ 507 0 R 508 0 R 509 0 R 510 0 R 512 0 R 513 0 R ] +>> endobj +507 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [105.602 750.9806 118.6329 766.9208] +/Subtype /Link +/A << /S /GoTo /D (page.47) >> +>> endobj +508 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[0 1 0] +/Rect [318.743 569.9146 347.4649 579.4488] +/Subtype /Link +/A << /S /GoTo /D (cite.D05.3) >> +>> endobj +509 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[0 1 0] +/Rect [378.4463 569.9146 407.1681 579.4488] +/Subtype /Link +/A << /S /GoTo /D (cite.D05.4) >> +>> endobj +510 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[0 1 0] +/Rect [143.5685 516.2209 171.623 525.6505] +/Subtype /Link +/A << /S /GoTo /D (cite.DHRY) >> +>> endobj +512 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[0 1 0] +/Rect [403.9487 440.4179 432.6706 449.952] +/Subtype /Link +/A << /S /GoTo /D (cite.D05.1) >> +>> endobj +513 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[0 1 0] +/Rect [162.3058 213.2697 188.5471 222.8038] +/Subtype /Link +/A << /S /GoTo /D (cite.VMC) >> +>> endobj +506 0 obj << +/D [504 0 R /XYZ 74.4095 738.0292 null] +>> endobj +264 0 obj << +/D [504 0 R /XYZ 74.4095 720.0964 null] +>> endobj +98 0 obj << +/D [504 0 R /XYZ 74.4095 720.0964 null] +>> endobj +511 0 obj << +/D [504 0 R /XYZ 74.4095 503.414 null] +>> endobj +102 0 obj << +/D [504 0 R /XYZ 74.4095 485.703 null] +>> endobj +514 0 obj << +/D [504 0 R /XYZ 74.4095 130.5798 null] +>> endobj +503 0 obj << +/Font << /F26 180 0 R /F31 192 0 R >> +/XObject << /Im1 171 0 R >> +/ProcSet [ /PDF /Text /ImageC /ImageI ] +>> endobj +521 0 obj << +/Length 3873 +/Filter /FlateDecode +>> +stream +x??M??6?>?"?0qm???????[?E??C??ck?s???????_~I?=~]?`??(?")?J?K?????m?I????J?c](?{??????H??? $?o?"y?f??? U???W??X?o?7?p?G??7?1??y?^??%I??*?*V*9?".????}?%q??V????i^??4q?/?_??7??O??????WY?`_U?j8#?????????T??D?V?j???n2?06??)8?????T_?G? +_?5b??p +?j??????Ng??v?2??5t????f??my??????SOr.????$???????''^$e?????u?#&?\zy??WYE???l????P?u?'F??;M??? ??L??*?O?n?=???!?Wy??????~`????7?.trV?{??%?????0>?\??????[ ???M??+?????~{???????? ????o?N?qrG??P?C?? ?IW???p?#??Zc?????O?g??+???Ef???n???k??Lg?H??, ???a?k?#??]????[72?=$???????[???` OZ???5s????z8??????'??Y?6uu???f^?UQ?u?{??d?+[b8?D??R_a_?P??????S? ?????????????KQEAsZ??H??$??V7 ??v???g?=??e??|TPB?-n?<4?#??u????[?B~?????%?w???g?xh9?-?tq???C??????k????!??8]^?_^!?M!???8??3?? ??|?Mu?]????&? ???b??0????p???%?)???&hN )+??x;w?8?~??5???[?????z?D?~?e + ??oP??G, + ???exO@#????~?????p:Z?^??N?????Z?%U??u?t4?{???????[?25?'yF>N?}?w??9?,Y7??&? ?????h??mZ?s>-???A??JA??Z????E?????6?U??f?M? ?? ?u??&W^I????K?;J[?>p?? ?X???[?Lv????(?]`k!??8 ?? +|f?E?v?s??T'|PIt?k9?r???'???L?\??9[??e|~.'??3}??^`?5OLp??W??>4?q???k? ???gv>?K?i????~?i?@;,??)???q}3?$S9??Z?ja???aA']?@?c??2Wh???b?g?Y????????q??;????w????&?#???M??? ? +???V'?#p??T?G???~???G??n??=?A]?7??#|???D????cIA+q?i ??"(p!Z B??????{?US?Z3M?ZYtdP-????\?{??T`PX??0??\???$|'??{q?a???ch???h???? ?L????S8k-??x? z ??9?? ??[?F??)(?? +Cb??e??W.??9v??{?c&???=8??I$???H$?9?]??+????????8?????T?E???i?{??|???????_??{+???????u?L9??L? +??+S??xg?,`(?K8M????c?s??:>????,f at d???e??Fq=D2?, ??U?so???{lN???/y?;K????zX???? -%??? E????L>?%_??~???t????~@^9,?7C?n?\?u???y???o)8y??,???H ?_P??U_???w??IPf#????????J????w???M?[i????????H???/ ???kd??c+=&p?p???U?\i?tH??H??M.?????? +g?cB?@Q??=?fh0?Yqt?0????? *9Q?? ??\?Zl)gB??-?M"?r?D??a??a???C!*]?+?S???JA?}p=/O?9HJ(V at c???(W?9856?Iy|???%%?[?ZT?2w???Y??I????X? +??O7?~???F??`9?96??D?G?%+??z?C/C?Iy??> endobj +523 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [105.602 750.9806 118.6329 766.9208] +/Subtype /Link +/A << /S /GoTo /D (page.47) >> +>> endobj +522 0 obj << +/D [520 0 R /XYZ 74.4095 738.0292 null] +>> endobj +106 0 obj << +/D [520 0 R /XYZ 74.4095 720.0964 null] +>> endobj +519 0 obj << +/Font << /F26 180 0 R /F31 192 0 R /F36 312 0 R >> +/XObject << /Im1 171 0 R >> +/ProcSet [ /PDF /Text /ImageC /ImageI ] +>> endobj +526 0 obj << +/Length 2568 +/Filter /FlateDecode +>> +stream +x??]??6?????2P3????!?\?8 M????,?????Xr7?_?E???M??Kj8?!?{h???g?i?"????fJ?y?,? ????? #8k???????x?>L?&R6J???n?ie??&????????????:?t?N????Z?( ?S?}??*?A??q^???????????????h??X??`?????????O??yo?2Wy??C???X?GiJ??? it;?]??i??????,\?q????|w\:???'??o 1LpO??w?M???7?od?b}??5??_?]UV?Mu?/ 8?:?=U[e???N??,?????R??????/ ???h|??h???????????4Syh,?+W&??????-???XP???gT?29??qE??b??@??o?+Mo??? 1???$????Go0????d?TE??????d? ??#?N?q?+kse?W?????Z??G?E{p?X??????!??????R3v??2??a?rr?=??D?DA_?p_x^?o ?'6OB=3?? ?:?2F>???1?7B??6S??cA??'bB[? +??h????h???g-???\j? U;0?|??F?W?1"P?#G??V?*?m??X?G?+rX?:X????9Cm?3=????8? ??W ??P???F|4{???'D??????-f??? LjJ??ZV??I?6t?D?=??????z?D?"^E"N?r?????a????!M??p?1?&??Z?Y???\????5?T?1???>?Vq~?}u`?t??=:l5g>i????n)????I??p???E[ +?$?`o)?t0?_?~?r??? VlF??N????O(??????x??D?[???4??B?? ? +??^?????# Q??%Ha?wwiK???I?6 G?64????H?n?>b ?7?.??_?Z?6?M#?N]O?WA?O??C????? ???.?>\'? ?)?e!??f'8z???0@?k??$m?????"M?TX??x?x??L?? ??&rt???H ??"???c?mp?8?*q?s?f?wz??|??????+$?\??2?g?l?,???BPT????????D?|?X)????o!?:?Iy9??Z?{??i??";?5??????{????Io$?k]Y^?????;???lf?????S?m???luqQD??([???????=r?[?b.R? 6??2?)D???y|?N>h%??`k???y`?'??? ????W???c?????$H?%??Q??????H?????=: +?c?W?9??8?[C3sQ???1?g|?k}??Z-????g9r?q at 9?T/????3????X9n????! ?2I?el9A~m)x?R?r?+??zp)T??o?i???\tJR??E??D????f????????Gg?5rf?$nv???=???0??(x;Ag?z????9g `??z[ ?m ? ??%??v[?P?J???O?>u/&?;=?^b???s~?????uC?2[?;?????L?\+?e??(AE? 6?*x91??[%?g???j????v?6\????x${???X?.{???G?o??U???????~??e?????&?L??????a?????????x?y?G??????j!?Xo[A=??,?? ???????????\???tns?[/??2I^?$?Z?N??0??5I?????;Y?? -?? ??????v???8?:gqw???? ???Y.G:f?t??m??xxV?dZ? ??K.D??x??Mt?????^?v??m???l)Z???l???(?r??i?.@?6@????(?)`ev\???K?K3?:?"??k?n ???QI?X?O?(4Y??Ra? +?/?I?Ya??2????%>????r?`6????> endobj +528 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [105.602 750.9806 118.6329 766.9208] +/Subtype /Link +/A << /S /GoTo /D (page.47) >> +>> endobj +527 0 obj << +/D [525 0 R /XYZ 74.4095 738.0292 null] +>> endobj +529 0 obj << +/D [525 0 R /XYZ 74.4095 696.1114 null] +>> endobj +110 0 obj << +/D [525 0 R /XYZ 74.4095 678.4004 null] +>> endobj +524 0 obj << +/Font << /F26 180 0 R /F31 192 0 R /F36 312 0 R /F14 259 0 R >> +/XObject << /Im1 171 0 R >> +/ProcSet [ /PDF /Text /ImageC /ImageI ] +>> endobj +532 0 obj << +/Length 3624 +/Filter /FlateDecode +>> +stream +x???n?F??_??A(`??^?'??? 6????MQ???T???????^??VY?,?E?lzA_?ab??????G???^??T?2?_Weu???K??Q?????&4&?`?$L??"???UZ87KX?;?~?Q6??*r???????????O7&??\+|?????h?o?G?-??? hP???'D???-uG????? R????ep\`??????@h?K???3????????'=???ax??VqP?m8???I? ?~??s?I???????T?>?? +f??g????Ex1%?m??S_?N ?tm???{?y????Z?M????!??m??,????2RA???+z]?T??:???$????FS??????yaL?????#?t??s??1??pwjKd\??^(t;~?:??P?|? ??8?}]?e??O?z?h?u?u????$????,S?????6%?F?c##????X?f??P?F??R?q??|????O?? /?E??????_????U? +????! ??D??`?8???0 ?k?]??MUl???????++~??TS ?O??2$???<=????h?X?d`????W#?NC_Sqa?ONb???Z??!t?%?????'y??_t????L????%?x?o?!C????c,??h ?+???A?5???G???W??????\?&`'"?)??S??:?????:??l$????M??h??"??_?V?5Yk?? ??JE???M? +Jnz???"wn????W??Pe]?BU?4??\??{z??;?r5J?;?b?? v=??|????Mj?3 rYP??????(?n;??0?p???????F?-????*???2 ?,????[|???8Z?M??E?^???W?? d????szrOQ+-?A? ??,? ??r???+?.??E$'??S?????x?y%q????)?i????????m???????U'??T;??r)??U?T?rk?,J???? s?????k??p6??"?!???Fe'OR???o???|??> endobj +534 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [105.602 750.9806 118.6329 766.9208] +/Subtype /Link +/A << /S /GoTo /D (page.47) >> +>> endobj +536 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[0 1 0] +/Rect [377.8176 449.8667 440.4023 459.4008] +/Subtype /Link +/A << /S /GoTo /D (cite.BLANCHET99) >> +>> endobj +537 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[0 1 0] +/Rect [450.9224 449.8667 489.7662 459.4008] +/Subtype /Link +/A << /S /GoTo /D (cite.CHOI99) >> +>> endobj +538 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[0 1 0] +/Rect [259.3562 397.3489 302.7928 406.883] +/Subtype /Link +/A << /S /GoTo /D (cite.FRANZ02) >> +>> endobj +533 0 obj << +/D [531 0 R /XYZ 74.4095 738.0292 null] +>> endobj +535 0 obj << +/D [531 0 R /XYZ 74.4095 567.3848 null] +>> endobj +114 0 obj << +/D [531 0 R /XYZ 74.4095 550.3742 null] +>> endobj +539 0 obj << +/D [531 0 R /XYZ 74.4095 88.3605 null] +>> endobj +530 0 obj << +/Font << /F26 180 0 R /F31 192 0 R /F14 259 0 R >> +/XObject << /Im1 171 0 R >> +/ProcSet [ /PDF /Text /ImageC /ImageI ] +>> endobj +545 0 obj << +/Length 3918 +/Filter /FlateDecode +>> +stream +x???????>_?K?T??& ???l?ZW?Y?S???%b$f)R;$w=??? Hql????h4? ??~?.????t??"??2????? s?~??`?>????&?v?????????BU??4+?4?a??%x???eH?(x?a???A??????]=Wmk?f???????????jH???;??z???8?{???oT?+?2b??hw?UX?????qd?|w?wo??v???Qy?I??\e?pG?????] g??$?,??g??0.A??Zg?N?h2?>??0??fi??$ +?,K?%xf????R??? ?P???#????F?% hb{>C/ ???-?I??b}x???gY?????m{????p????6??D??x????u ?Q??_?(9?????X=??48????d?y?S??F?8U? #};]?? >=??i??F?j6?6Z?4r?U`@|?p%q hQT?? ?+????/0: d????K??)?jt??r)?F#!?Z???w>?hc-????*???i??????m?y?>]]??1???? ??w;4?t??\n??(L?U?;XLr4? ??j?????6??C?Y6?i???c??C???x?,/?? ??wu%Na????[u????n?Q???.??eZp????`?OE??_p???%o?0?#A?0+!?_?? +???m|? 7??r????????Vxx???^\???&?r? ???!X??????@ ?!7??G??N??*?M?E!??A`?=R????~6yNR?????o?@_?r80??????????Vt???C????_?????C???3wI??vE7?=??=O?2N????l?1?X?? }??????[??+*IPHH(??ds?m??6?Z?H???m1??????C? XbS??e?HeE F?????Z|???????x?????h?0#?????.??.\?6?S{???h1a?6 w?.?|?A|Ts?v5????j`&~?<'k????p?3]?tV?y"??&????????&B?0.u?"ae???m|??L? \U??\TC?Ws?????> ????6??B??)?I2?:?6???yZw1? >k0c?>??T?3s?s??m?%??l?5????6???E???[0w?j?U?el??2?oZ??J0b?^?_?????|? ???h?B??q?V??&c??~/?4A?L%??(???7?> ????5????/???D?W??T9?gY???????qZ)????.??')???k??8??(L?R??k&: ???? +?? ????M ???"xT ???n??x?????Gde??ui\ +??? ??v:??S?U???BZ?5??????ol?R??z?<7O??[?I??G?W*? yT???oB?0I?%?; ?v????+?H?.??;u???>?^?????0?:`psa3?mH ?i?U^@??U???_?`{?h6??z?+'y??Wv??q?]'$???-?7T?XR?(??C?y?w??? ??S?s?6q????G??.,?|???}]0?o!,A??g[S?)k????">??2????f??W??w?????x^endstream +endobj +544 0 obj << +/Type /Page +/Contents 545 0 R +/Resources 543 0 R +/MediaBox [0 0 595.2757 841.8898] +/Parent 515 0 R +/Annots [ 547 0 R 548 0 R 549 0 R ] +>> endobj +547 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [105.602 750.9806 118.6329 766.9208] +/Subtype /Link +/A << /S /GoTo /D (page.47) >> +>> endobj +548 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[0 1 0] +/Rect [306.9728 516.495 335.6947 526.0292] +/Subtype /Link +/A << /S /GoTo /D (cite.D04.2) >> +>> endobj +549 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[0 1 0] +/Rect [261.4686 468.6744 290.1904 478.2085] +/Subtype /Link +/A << /S /GoTo /D (cite.D04.2) >> +>> endobj +546 0 obj << +/D [544 0 R /XYZ 74.4095 738.0292 null] +>> endobj +118 0 obj << +/D [544 0 R /XYZ 74.4095 720.0964 null] +>> endobj +543 0 obj << +/Font << /F26 180 0 R /F31 192 0 R /F34 291 0 R >> +/XObject << /Im1 171 0 R >> +/ProcSet [ /PDF /Text /ImageC /ImageI ] +>> endobj +553 0 obj << +/Length 3784 +/Filter /FlateDecode +>> +stream +x????????_1W8U??WrR$?%??ey?,8$v?6?/9??_?~?????j?n4@?_`? ?/?%?7A???????8??{?}{ +???T???y?F??????jw{?K_? 0?3? +C???z????* ??A????I?wy?U??????|???!?k[W??k???u?=?MW??C??U?0?ew?E???????2??A"?B?g&Ihz??$??;????vXV?~??j?D??:??#??^h>Lva??L?6?X?E9L???L?X??b???T??????~??m {>?????U?K?L?}????~?????? |?f?j???7??xx8????p?????f?????~?B ???0?3?????JX?w7?AY?>?A?a?v?1&?MKH}????s???[???O?Xmh?l???TZ???w{xm]V?=?nZx???=?A[2 ??~/???]?6BS5???x6???H??|?TyS>?{?}??S???????)Ng?Ap????l*8b???E???+V??=_r?d@??o??????????fh?U-c>Q?????T?'???????wy at i?K~?#/?? ??$???%? +}??h[??t?5i8?o|???;{nA8C{???]????la?M??b? ?J!???????????'??h}?H??1*?>??O(7RU28?^??&?-???w????????4?nO???5??"a??y?E?????-OO?o8????AE???x>n.R ?9?_j+?'i??[???~8?+`??.y?[????l???{??D??V +?;?S??)Eg???????6A????M + ???&{???=???K???[?:??p)BFT??Y???&??????p????(8?,??xJI at zg^i????????????-??S?s???????o??N#?/???N??????=??[Q?? ??q?3q?id????a:`?b???????o^?km??????+K?D????E?Z 1??T????l?  ?n{qV8??U4?9?4?}???1l??6???/W??1?{?%??????XXs?????f3H\!ul??W?2???T??h???????|_???(?k#????!JBil??U?ji?h?rB b'??<;?1@??18?L3Z,h?b???1???>,w???Y???e??7? D??'hwg????p?T?dB??Q???^I?B?hkJM??o???QUHoj?:qn'????d4??&AR??v??$#?^+?]R???>??v?Lt?&???i! ? H??'???h??1?]?f~E9I?S6?R?: ?o?@:[c?`?i)???hDL??????O?0 ?4oTNo??qU2O,?:?x?&Y?l? ??-?9??j%??Pc??+??@?/-_,?/a??`?F??J?>?c????\???!Z? Z??e'?4n??rCg?g???]W?G"l???????????Oi?^??NOG? ?????e?r??TQ? ?O???????%?*??y!f"??n?]??????'?O?0T???3 ??ci-a?s??g?8 b%??4X |??7? K??? ??Q1_???6?????Pe"tQQ???ZrD???????5?-???1??Dr???@0 ?+;lN?????@9Q?H?<`{g 7?!\>y^?B??q??jR ]=???,?u??!=?.??rx?E???????{Yn*?4??I???&????Qk7????X?e???;^???Rb\q??tRsn?)??RYZ?Qd*R?_???I$/y????????'? c?eU)?|e2?SY??Y?S?????????P:?????Z??v??n??p7f?oD?,?_Z?_%?8D?Y *1_?2wT?????O?????*F??[9???B?(?u?5 G~??U???'????jk0?l<]U +???M??m:???3k??C??$0I???d?????????z??(z? ???6V??@?@4a?e??B ??\????%?w???b?C??????J?2??*??E +?nR????u???1SA????$??4@???D +x?????? E??'W???`05??ID??|2?2??9Z?????c????=>??s????: ?S?????>?j?^? R?j?=Ng ???A?????J~?"??\H??> +~??V%31?c? ??? j???????c?.l???u????~?|??`?m?????w?W~(?UH?F9?0??'?]?j?S?L?+D? ?/?er2?C?&??/??i????d?4???bn??x?p??n0?IFIf?V??k???i??i?*ZD?a???D?1p??????0ny??u???/???k?p????R????&?!????\ a?j??D?JF???Nhz???????wLX^?0[9R??G?????#jZ?8A?????5?????B@????uH??7?<:?U????R9!?k?4?!K?[b^ ???]?u???Q??????&?c??????????O?endstream +endobj +552 0 obj << +/Type /Page +/Contents 553 0 R +/Resources 551 0 R +/MediaBox [0 0 595.2757 841.8898] +/Parent 515 0 R +/Annots [ 555 0 R 556 0 R 557 0 R 558 0 R 559 0 R 560 0 R 561 0 R ] +>> endobj +555 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [105.602 750.9806 118.6329 766.9208] +/Subtype /Link +/A << /S /GoTo /D (page.47) >> +>> endobj +556 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[0 1 0] +/Rect [489.6438 621.3793 518.3657 630.9135] +/Subtype /Link +/A << /S /GoTo /D (cite.D05.1) >> +>> endobj +557 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[0 1 0] +/Rect [166.9926 549.6483 195.7145 559.1825] +/Subtype /Link +/A << /S /GoTo /D (cite.D05.3) >> +>> endobj +558 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[0 1 0] +/Rect [226.3069 549.6483 255.0287 559.1825] +/Subtype /Link +/A << /S /GoTo /D (cite.D05.4) >> +>> endobj +559 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [307.3462 535.7305 402.7954 547.2273] +/Subtype /Link +/A << /S /GoTo /D (the-gc-transformer) >> +>> endobj +560 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[0 1 0] +/Rect [363.1104 459.9846 403.8672 469.5187] +/Subtype /Link +/A << /S /GoTo /D (cite.SQUEAK) >> +>> endobj +561 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [214.2531 296.6271 429.9614 308.1239] +/Subtype /Link +/A << /S /GoTo /D (the-gc-construction-and-testing-framework) >> +>> endobj +554 0 obj << +/D [552 0 R /XYZ 74.4095 738.0292 null] +>> endobj +356 0 obj << +/D [552 0 R /XYZ 74.4095 696.1114 null] +>> endobj +122 0 obj << +/D [552 0 R /XYZ 74.4095 678.4004 null] +>> endobj +562 0 obj << +/D [552 0 R /XYZ 74.4095 232.0892 null] +>> endobj +126 0 obj << +/D [552 0 R /XYZ 74.4095 214.3782 null] +>> endobj +551 0 obj << +/Font << /F26 180 0 R /F31 192 0 R >> +/XObject << /Im1 171 0 R >> +/ProcSet [ /PDF /Text /ImageC /ImageI ] +>> endobj +567 0 obj << +/Length 3674 +/Filter /FlateDecode +>> +stream +x??]??6?}???j?Z??f?.?????0??t???C??U??%? ??&????????J[????Q?oh?B??5(8J??dx?;?Q???I?O<?5 -????r????y??@?^? ?????W?+??E?pn?h?LTX?)[i3?J ??iKQ???_?* ??????B?d3?=M?6]????r???????m???_}??q Ol??)?Pe????e2I?&9??? ?w]??;K>ifT?x?4a=w????{H/"0a??????Y??j[t?9?\'????*??G0K1?????qW??????iA-????(ypB?)??I???Q?|????????6??")?@???Q????q???2?\?W1??!?EiT??XV?xN????&?Z?o?M???)?lgL?8?{??????????? y?b?@?????5?s????????%?drSh?????z)_UX??G??#=??'MG??v???:??b ??0??b?+?-D??y?[???M?Xa????H??? xA???x?8?85???{?*??x???%H??4r;*H????C??=??_?[??y`??5:???-+:???"??V???4??h??%?{?????qY R"OKH??os??W?'???V6X?????`zw??Mq?????0?kdZSXG??xl8t????\?q????f??0+?b?????dq????Y??je6?,s?l??e???q??l?(??4TP???x??w??}?n#*%Ih"2????Q?&?&?x?W?r,???NR???}?.???^%?V?P{?^?&E) >???`?????n??q ?0?v[??+?P?%???P?+???j???J?5E???'}??0?Ud?f? *$$z? c?p,??A????U??Tm` F??2P*Ur?Z??"???N???a?]j{:??N"&????\? ??:?????&H?????vZ;?????? oy??d?N?_d??J h()????r$;?U? ?m??H/8[?x?6GN???8?? l?A??9?7)?Q?o??m??EN^? +1L?????urg?H?V +Sm?G??[O ??s??g?^nV? [ip??:?j??0?8???d????R??+KI??x2@?????8~??^?($????8??Y????$#???S.?2???J??X?k???!?c?????"`rr8??? ?rY\?(??z?h??#??D)?Eq?CkG?7???{???????&?D? wf??? +?0??JRD??(?r?d?nB?@?????Q#!???Xn&TVcu??????t??P?*?G,????zO0:????.?\?-?E`?Ur?Ta`5w? R??gq?Kj?F?^#???(I?q?a?bY?.?@?y??3??p?t?????? -T??\v'???@DR{?d~r????Byj?!???nm??6=?W3Y???~??O!&?W??}w????N?q?,^??;???v?@??? , "????????LJk?????:?????d????I?q???qX??o]??V?D??.?t???`???B??i??Yu+?h??b??N?p??S+gH_ +F?~^?F;9?????????SY??6??#???0???'?'??"d???"??M??z6?R?i?J R?l?!H??(??:????)u5K?Pq?o?$??6b???R??i) ??S]?? [(?????\?=????=??7????Sk~E`??A*n?#?}Aw???? y??f??8TJ=?Qu????]?5]??w/~???=????|??$?????[?gN_S??d?I?????5???x???@*?B???Y?????pE????7?H??????X?g]S?o?x??? )???=f  #/?q?0??e?(Kw ?.?G?XWgJ??X?*???i4o????`?Dy?{6??$?H???8#?L}??P??$??hk????5??;???&P ???: ??n.???p???S`??????p?k?m8??otjRh?--P??jQ:?r???K??I,e??X;? ??Y?f???????\2???V?N???\???ji???\??=?c-K???n?????o]}D5?%??n?p4?FK??) l;Q:xr?Z??????? ????L5?;??O??"?????m???"??xfj?e?i?~?dy??SP???4?0?Q??/?Xr?B?kF?o.?~S????????@k??`7O?[|Ket?&?????? + S?x??p??0?/9???_qp??n?????o?8????P? v???I?!?????o?Z>?sR???2JCmT,??by ??,??v??~ ? ?&?Vg????`??X?e?0?????z??6???U??NS?K?a`????H"??^??x.I};???????q??a????Pj?}/1??7?!??,???????endstream +endobj +566 0 obj << +/Type /Page +/Contents 567 0 R +/Resources 565 0 R +/MediaBox [0 0 595.2757 841.8898] +/Parent 577 0 R +/Annots [ 569 0 R 570 0 R 571 0 R 573 0 R 575 0 R 576 0 R ] +>> endobj +569 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [105.602 750.9806 118.6329 766.9208] +/Subtype /Link +/A << /S /GoTo /D (page.47) >> +>> endobj +570 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[0 1 0] +/Rect [321.2003 697.1823 351.6358 706.612] +/Subtype /Link +/A << /S /GoTo /D (cite.MMTK) >> +>> endobj +571 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[0 1 0] +/Rect [257.6944 667.1899 283.9357 676.724] +/Subtype /Link +/A << /S /GoTo /D (cite.VMC) >> +>> endobj +573 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[0 1 0] +/Rect [241.1365 557.6184 278.8051 567.1526] +/Subtype /Link +/A << /S /GoTo /D (cite.BOEHM) >> +>> endobj +575 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[0 1 0] +/Rect [475.3313 191.0109 518.5389 200.545] +/Subtype /Link +/A << /S /GoTo /D (cite.GCSURV) >> +>> endobj +576 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[0 1 0] +/Rect [89.7673 179.0557 108.5467 188.5898] +/Subtype /Link +/A << /S /GoTo /D (cite.GC) >> +>> endobj +568 0 obj << +/D [566 0 R /XYZ 74.4095 738.0292 null] +>> endobj +572 0 obj << +/D [566 0 R /XYZ 74.4095 630.358 null] +>> endobj +130 0 obj << +/D [566 0 R /XYZ 74.4095 612.647 null] +>> endobj +574 0 obj << +/D [566 0 R /XYZ 74.4095 252.0145 null] +>> endobj +134 0 obj << +/D [566 0 R /XYZ 74.4095 234.3035 null] +>> endobj +565 0 obj << +/Font << /F26 180 0 R /F31 192 0 R /F36 312 0 R /F34 291 0 R >> +/XObject << /Im1 171 0 R >> +/ProcSet [ /PDF /Text /ImageC /ImageI ] +>> endobj +584 0 obj << +/Length 3852 +/Filter /FlateDecode +>> +stream +x?????6?>_?#U?????????:?T???@I?k?T?????o?????T ?? 4? ?Mj??a?&3y?Bo??hs???????I;????^?????C?zs?????? M?0Q +`????O??;?G??( ???;g?????/[~?v?X6M????;??oM???????)?#?ZX?f + p?Mu????Np?????h?NC????^???x?c5@?T?`?????MhY???'?L??/O???%?I? +??$??Y;?N?@?#???=??T=#T0? ?&?y???@~ +?????lt??"??M?O)?????O?0?????.??r?IB$?e?P?1?.?,??,??_??5(? q?a?5r?@???p??W???J????yS>q?YX?1?g???? ?%???G???I???????s?63????}?e?O???6?????q??2???t?????F?I??s??5?p[?g?N??N ?+G????????@??y?D??? ?K??i????{ ????L?S?\???5???(P ?p??%`P????e?:;??Wk????? >????q??]?LP} ?g??5E???1.?{????????V ?????k?E?.?N?H?? +?q??7?0???rZvTB????? ?????ALh??\1d,X??2?[???H?SJ?z).:??j?G o?7? /???!??????#Y????E?&??T}c???S?$`:?T?U+?3=>a??\?_??)?#Y???)???C#I?????? +.?{?e?{???lfRI??e?????? K?hX? ????R??@?u?3X?eC????7??c?????~?Q?,?W[?0e???"??X.??????t??(qB??7??0N???G;?/X)?,?R ???O??y?f??y???z????? +v??? +????l???D??y= ?? ?>??"Mn???S??_???i r???,?H?)?J?l?*?$*^z?r?w???Ld?????Oo]l!-?8V?l ? ??z????#/5O???")?p?????4 \??:O??n??.???=???E????nq???]K???1nw?)?X?,z?N3??v?~9T?+??$v??????4??|:?L!??"???h???f???R0v??oN??UT?89??X????|??"?#4x8>K?#??????)?\????GD??T???fU???R???o??B?/> endobj +586 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [105.602 750.9806 118.6329 766.9208] +/Subtype /Link +/A << /S /GoTo /D (page.47) >> +>> endobj +587 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[0 1 0] +/Rect [224.8143 637.302 290.0191 646.8361] +/Subtype /Link +/A << /S /GoTo /D (cite.DETREVILLE90) >> +>> endobj +588 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [503.0731 540.1601 521.8625 551.6569] +/Subtype /Link +/A << /S /GoTo /D (the-mark-and-sweep-collector) >> +>> endobj +589 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [73.4132 528.2049 205.7376 539.7017] +/Subtype /Link +/A << /S /GoTo /D (the-mark-and-sweep-collector) >> +>> endobj +590 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[0 1 0] +/Rect [76.91 397.2743 103.1513 406.8085] +/Subtype /Link +/A << /S /GoTo /D (cite.VMC) >> +>> endobj +591 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[0 1 0] +/Rect [239.354 230.4687 269.7895 239.8983] +/Subtype /Link +/A << /S /GoTo /D (cite.MMTK) >> +>> endobj +592 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[0 1 0] +/Rect [145.203 218.409 170.4381 227.9431] +/Subtype /Link +/A << /S /GoTo /D (cite.JIKES) >> +>> endobj +585 0 obj << +/D [583 0 R /XYZ 74.4095 738.0292 null] +>> endobj +564 0 obj << +/D [583 0 R /XYZ 74.4095 469.6446 null] +>> endobj +138 0 obj << +/D [583 0 R /XYZ 74.4095 452.06 null] +>> endobj +582 0 obj << +/Font << /F26 180 0 R /F31 192 0 R >> +/XObject << /Im1 171 0 R >> +/ProcSet [ /PDF /Text /ImageC /ImageI ] +>> endobj +598 0 obj << +/Length 3273 +/Filter /FlateDecode +>> +stream +x?????4??_Qb]]??so??? ?*[]??]???i??|??]??????TJ?w?:???????"?e*????v??.????](4Ktp??|?{?6Jwa??8?v???s]F????? I?'???-(E7??x7.?1J??U ?_?[w"???????"?????#o PR<|??08??t?'???r???@?6T?:qA?\?{?<3????iK!??iX ]??~???n??Y???'?K3?2@???????.?l???)~?]2?PG???D?T?Si??e7@??'gv??< ??X??? ? +????}??1|+d?O???t?L? (??#???4t?????J??Vl]?hb?&?\?|^M?%?xd?#?H1?u?b? K0?.??3,0$? ???????? ????x?????-?/??B???^}+t?@%?O?7??6??F>5?q` +?f6??~?? ???27%??_?Ps&???T,y?????70?l????Oc?????`85?/????????m}??????5?p?2????Z`#ka???K?k?e"?????r???1??????????????W?8?YXz?V???4?'?3]?Z?,R??v?+?????TR??9#)?O???l>?????jq???,?`?U??aM???^$kpD?Q/~6?? C(??*??V?2v? 89?}2??rx +??"????[?fmdbh?????;??M=??????\??8?4?mD?yj? ??l9???????%??"W?t?9??GoE?E? ???MG???"?,??j?9???B???+?n?? ????? `?b????a????????E??FX??\r(>???+??2W??Wu???????rL???m7=??rh???6(??}~??B[4?????y??O9????????=???r????6???O??Y???=bey?O~????^p??=?u}e???????2"> endobj +600 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [105.602 750.9806 118.6329 766.9208] +/Subtype /Link +/A << /S /GoTo /D (page.47) >> +>> endobj +603 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [110.6344 206.9809 246.934 218.4777] +/Subtype /Link +/A << /S /GoTo /D (the-stackless-transformation) >> +>> endobj +599 0 obj << +/D [597 0 R /XYZ 74.4095 738.0292 null] +>> endobj +601 0 obj << +/D [597 0 R /XYZ 74.4095 478.7592 null] +>> endobj +602 0 obj << +/D [597 0 R /XYZ 74.4095 369.1877 null] +>> endobj +596 0 obj << +/Font << /F26 180 0 R /F31 192 0 R >> +/XObject << /Im1 171 0 R >> +/ProcSet [ /PDF /Text /ImageC /ImageI ] +>> endobj +606 0 obj << +/Length 3489 +/Filter /FlateDecode +>> +stream +x??k?????? +j??Y?DR????=???=?r??@? ??Z[=[r,9?????(Q??6X`E ?C????????d?LlTaWN??J?t?9??????$???H?????W???*1?6Y??{X?*???Y?$?????????u????rq???Z?/????6UQ??p\????:???C?n???e???????mx?ew?6}w????_}??U?V?D??q??7 +8??{?????De?-?t???m?-??S???| ?0???$???t?n???Lg?j?+?X??:????`??T??x_??-?N???Oe???V9??b???[??R??? +?0??Mb +^?(???1Y?io??Y}7r?]i???"N,??????Zm??oo?????QqR??o??bc?5?n??i??tI?6Uq?e???Bt`?E^?\[i?? ??^?????Z4?_?m?elO?y0?%S\? ????????????$?vH????jzF????????/{??[ ???H?*???8}?+??"9?????3??{?5?&.??#??~%qa-_?????5???????J?I=?????IN???1??R?d?5_D?????X?c?L+e?%?????l?~rf!x1m??:$??,4Z1*7D??v????:U?nW?Tt??]?p????_xPn??????_?t?j?? ??? + ??^X ??????uj???tA?'?U???????L?[e8??K??~?O??C?Y'9?S?o?X?fi>????4?`kG?:C&??!?l??????0???? e?*?A???????tya?_ZBjCK?E?z???J?????{??KGa4?? ?m?I????J???2U?w2??k4?? ???H??P?#??????wE??go ??B?g?8`-?q?2????:d/????G?+/>#????7????A??3 ?>/? ??x????{Pn]?Q?x^????? ?6m??uC?K?O3?D??^???IR?/34`-p4???D?)K???1???e9?????u?W859FR7??? ?61t?L?a +a??b Pl?/?D?+F}???AS?]????b}?`?r??C? +??`?????/????9????{??T???oc?R?<5??idt??,*#?am?O??v?'^n?vI?)?X/,?EHA?????Z??6d?$-~?????z?????k at i?&??n?x????????@?[87?Fq[?? +'?^????QAn?i l???R?:???!S^????vj?f?%?ZN??O8/?/?I + 2G???K`?e1`=????C f???^RJ?kX??????%&??,?? ????B? ???? ??c??^????d?C??0?a???p?Z?@???[V??t?\?)?f??B????4????O?)?;?]H&??]?K??16P????j>?6D?V??,???&????R?7)???~??acW?=?S?{H?C??4??~?s??P?Or?U_q???r~_AQ????+???$K??G?,?H?$A??????"4??Ox0??F?i0?/???HoE??\'???Bx??E??P7?Xv???p I?????u??&QJ????? ?d?K??A???????*~??^:??6fI??&???J ?$?? #B???6j??]?H???!?}?ke???7U@?T/???P1????`??O??%?/?&?r?'?D???8I-??W??Ig]v?~?????~?I???)????u?????v??t?L=??? ???.??????????]????X?m;?F???R?b??d???R??3?4???l???&i:)M???G0????~?p?q???&?H?s-74 H?0?>^????9O??)?7?&?l#??4 ^??????????4?X??p??Ts??X???i?g?`$|,l?wLm?/??FQD?]?~p??:D??DF????> endobj +608 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [105.602 750.9806 118.6329 766.9208] +/Subtype /Link +/A << /S /GoTo /D (page.47) >> +>> endobj +613 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[0 1 0] +/Rect [137.5151 450.0375 156.2945 459.5717] +/Subtype /Link +/A << /S /GoTo /D (cite.GC) >> +>> endobj +614 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[0 1 0] +/Rect [176.5013 450.0375 219.7088 459.5717] +/Subtype /Link +/A << /S /GoTo /D (cite.GCSURV) >> +>> endobj +615 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[0 1 0] +/Rect [256.5345 236.3676 275.8818 245.7972] +/Subtype /Link +/A << /S /GoTo /D (cite.DEL) >> +>> endobj +607 0 obj << +/D [605 0 R /XYZ 74.4095 738.0292 null] +>> endobj +609 0 obj << +/D [605 0 R /XYZ 74.4095 700.0417 null] +>> endobj +594 0 obj << +/D [605 0 R /XYZ 74.4095 521.1898 null] +>> endobj +142 0 obj << +/D [605 0 R /XYZ 74.4095 503.8668 null] +>> endobj +616 0 obj << +/D [605 0 R /XYZ 74.4095 196.1255 null] +>> endobj +146 0 obj << +/D [605 0 R /XYZ 74.4095 178.8025 null] +>> endobj +604 0 obj << +/Font << /F26 180 0 R /F31 192 0 R /F38 612 0 R /F36 312 0 R /F34 291 0 R >> +/XObject << /Im1 171 0 R >> +/ProcSet [ /PDF /Text /ImageC /ImageI ] +>> endobj +621 0 obj << +/Length 3909 +/Filter /FlateDecode +>> +stream +x???K???????)j?\4????'F p|?"?B]??RF%?[*?'?>??<$?}??????%??T?\??????{??????2??\???????1I??|??yWP"?*?%Q?A??o?O_~???????9a???2??R C??#?Y????p?Z?m?6?????(h?ZuC[=?U66}? ? ??0??????lW?R?Aw{&H)??6/???6y??q???????\)??P?w??????Xa?? X3,????????r???o??????^?oj3?~????>??????r??R}?J*A????I^?4??uG??q?6W??_?,?8?S??>?????_v??yAJ???$L????????>? * ??l?????AJM???????|?A?-?fD?))??+3xa?y50hJ??????LZ%??T????\c????Y???.]d?7?S??????)Ouw8?q???i???|?a?OU^L???w?N^dX??j????cm???????6??`??(??```.?P???H?????t/??RY??MWfrh:???L~}?Y}??????gDq???;b??????W????G? ?r?;???#?"n?N)?????JP?????>.??l_?N???S{^??1???/%?C???=S? F KA????[F?`w?1???v#X +d?X??8Zu?8Vv??Z?)? ?$??T??1v?Oe????xm?????c????H8?????fmO?[kJ??_??JE8z????R???? +???\p*????M8?XnM~a??:.K?S?l???vh???-f?n?%(;QSn????v?1.W8zq?c???5) ?tB???!Qq?Tj?gKp?? o??I?D:?S?q?RrB????!?ot* +[!????e?*??#?FO?????F??z?$zhDzh +L?mf$?0#??3#??v^??Hg??? ?J????U??8?xorm??\?????6????????d?????"?N.c?3???????q?^l??L???"*??"??hy??Lc??H?;???Hg??L ??Vw??RT.??p?i/???????D?????A"??????F$???8"??6?gB?R??? +?E????Ja???DO?F???????L?w?y????????????g??C=???? ?E' ?o$??? wDNY??=?L?qfH\? ??D%????t=E?"g????????|?? Zjy??'?@?b|????^?????_uO6? ??x\?}? ?E:?q?3.B?k?f\$??q??qJTJl??Nc???H??P$L???t?|??P`XV?y?)? ??5Z??A?~?[?mZ?&?E?'?AW??,B?t"=-?"gZ?"I?y{?N??ET??E?????tVD5zV,????$??3*$4??;q?i?Lc@??HO?{v??Hg??? ?\~?>DH?9???~??#S????=????????d???3$? ?E??I:?!Q?3A??~??J?HL??G(?`?/@?) ??????????$3??????M?? ?????? +?S?C?TS?w????????P?r/?Tfr??Y?];?X ?C????z??zr???>??????????n?k?W?????5m/????!??K???q]??C??Fe??t?f??E????????j??g???zLA?j]=??f???Q?U{ j?9?_,?Xy??p??E h??(?`??]?y???8??#?b?9QC??@?L????S???4??z???J??3 ??O??atK?:?N???k??kwp.?L?g????????????"wBM?9X?G??L??27?U???@??????*???A??k=?????p??R?u?E^L?0???\???5em?????? ?? ??F???????0???\?no??;t?{?3B?v??/?z???d?B??3s??? u_??3F??0DO????:?`e?????L??Fv3????? ?V/??YgwNX?&??d????K?r??q73Rk??:???????'???????>????j??=?s??{Y3?aO???? ????okI???`??6w???2???*?E??X7?p???4:?3.???e??!f??????????g??]???????????Q :?s?rr{v???b:?@?????9 ??A0??:??[+?y???????o?k???N???+????~????]?uo?N????=??f???1l??$?d???ii?9,???;???7??YZN]???????%#]x????K&{?????????9?f?E??sM`'????????B???)FZ?[v{?w.FM????v???????v??????U???iw at jN =;a?+?0 ??p7(????S???-???b??Js#?__N?,nS???????7???]??i?-i?{(?{_?M??'U??S??6???l?Z???:?\??G?vyt?9??D?U????m??o#1?endstream +endobj +620 0 obj << +/Type /Page +/Contents 621 0 R +/Resources 619 0 R +/MediaBox [0 0 595.2757 841.8898] +/Parent 577 0 R +/Annots [ 623 0 R ] +>> endobj +623 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [105.602 750.9806 118.6329 766.9208] +/Subtype /Link +/A << /S /GoTo /D (page.47) >> +>> endobj +622 0 obj << +/D [620 0 R /XYZ 74.4095 738.0292 null] +>> endobj +624 0 obj << +/D [620 0 R /XYZ 74.4095 660.4651 null] +>> endobj +625 0 obj << +/D [620 0 R /XYZ 74.4095 189.357 null] +>> endobj +150 0 obj << +/D [620 0 R /XYZ 74.4095 171.646 null] +>> endobj +619 0 obj << +/Font << /F26 180 0 R /F31 192 0 R /F36 312 0 R >> +/XObject << /Im1 171 0 R >> +/ProcSet [ /PDF /Text /ImageC /ImageI ] +>> endobj +628 0 obj << +/Length 610 +/Filter /FlateDecode +>> +stream +x??T?n?@}?+??0???oM?T?T?I?????F???????b?`K?%??93?s90B???? ?S? ?;NMB? +?o 8????Y7????k?$?9??KAX?A????O?l??g9?4????,???????3N?2?3.?E]?u?5W?:?M?????,Wi_??|?^?E?e????;????2x Jr&?IcBz?????}?????X?????@i?b?????? G~>vm?p?????,?3??6????Y??z?g????????Un?S??S????J??b ?Z???7BA??d`????%L?????x??a??M?p?F ?3?u9` +g???)Yb?? n???????p??DJ Rai??N~&??#4?^j???C??l.??Q`|Y?d?sc??+?Y,??9?O?h?n??n0~?8???????|????x??`?uY?E> endobj +618 0 obj << +/Type /XObject +/Subtype /Form +/FormType 1 +/PTEX.FileName (./graph.pdf) +/PTEX.PageNumber 1 +/PTEX.InfoDict 632 0 R +/Matrix [1.00000000 0.00000000 0.00000000 1.00000000 0.00000000 0.00000000] +/BBox [0.00000000 0.00000000 285.00000000 413.00000000] +/Resources << +/ProcSet [ /PDF ] +/ExtGState << +/R7 633 0 R +>>>> +/Length 634 0 R +/Filter /FlateDecode +>> +stream +x???M?&9?$??S? r"??'????f??,k????/?;"2?g$?E5??? : ?????????????????????????????????????\?????O?W?V????s??z????????????y?z?????_???3?????]??????=??i???>kG??????>?=?????Z???l^??T???)??C???77?n?? ???Q|????{??(???]??j?+??????-???S^_?z???2J??^m}???r +??q????Z?????~??j????????z?m???|5??<5u(????????W?????P??? +J????K?*(???????UP?W?????????Z?????J???????????3?g??J????yg?%}?K????C?:?zrt???hN??\?????tc???????w??'{Fn?\k}???XQ?.??k?Tq????????g???????t??}n?\{t?Z???pN~o???? +l?? ?}c8z??/H????~.????? ?a??????=?Q???u?~(es2?????g?????=????;??,F9????[?????????v??8r\ ?b?b??j4?)??q?????? P??7??????7??@????`s]zIe?V??\?????~?J ????5[?????la? +??V?v??Q?????E/??`+ Ew?? +? &Z? +:?Q?n?V?K??j1?IT???STP??????4???{??7m ????[?xtvkUP????|Q?s??"??O4;?V9??u??m%?2o?????'Jl?-4?????^?????5??[????v?j? ???Uh6W?u???^????RB?9(eo^1?????U???a????n??;?????? A?????r? +???-?%?3?2?_?b???A??c???_(???|m?????ov?:?Ut?.??1??????f?}Q]?k?1;[???`??p?[?? ???*?[?? ???V7????_)?W??)?:n???AQwy~q?? ??|S9?6??? ????Kwy#??$?????d eoJ?9;???o(?"???-???fO?o???z???_?????EQk?S?~|????}ml????D??G?Tl????YW?]??SjP?VXK?Q??t?-5?@?0?pq??l?F?S?'S1"?)?????)????B???)??rqL_+?|w?lL~??????V?O??(YZ{?????B?_?P? ??????|???rN? H?B?[?*l_?&?)?Ho?????TC??C?? z?jP?{cq?e??????u?????????????+?? ??fqu~??O%?q]?r??F?=?? ?{? ?~??9???i/?&????}?????????l8??.?? ???S??_mE)???i&????Fy????????ha??U?S??oj?U???v????=?? +???{?????p?E}k????+???p??YLKX??3????????L?????????ml??Y??x??O">??????U????&_?R?????QwdkF??????H???s!`#?P6??pi{???? +/???????O Pd????=?????????{ 4Q????u??????]n?)????\??????U?,w6,??s??B?????-??)]>N [?OMm ? 8???.????????#z=iI?[ +Rv??wT??n!g???H?????YM?K??Q?<???5???2?[!?g?K????/??j?V??s??6Q??? ?[V?g?Y???????L????B?1:??*4?Z?????U?????f??? +-??????WN??????r???D???1?????D????JL??????????-'m???????????Tl8?4?0????O??P???? Q]?A?M+??'??ic?MKCz????wE{?A?Y $8???P?@??:UR??Z`?????? D4?$ ? ?P ?e\L?????F?#?1??????">Gww?????????!+ +P???????????J????(N?ycit?tl??jm??u?r @4??????FW??6_???M???C{??-???z?] J?????w??m???o???(????o????????R+l?/.???P?W1??8;?W?(???J?v?P???????W??q????L?????????z?~???-.ec?? +???7??????|??xnM????s?@ l?d?)??g?.?Y???/nm'?>?Z[V8l??C_P???????e??d2????? e? ???I???c??mD?? @mp??t???l?%?Y??|???\??}???E??&0f?!??2:?`?t??w ???\?n???6?v???1???f???1? L^~??E?w~??????'??@?n???_T>?-??qV-??{??Y?h?2YM-Z??}??h5)??????@??9???]mG/???D ???k*5????D`???ow?X??c?K;???Rt????????1j???1?Uqa\????P?S???? 2??02?i ??~???HRZI?8>?????M.??q????V?B??????X?s???t +?V ?'?????????!?X??+?N??nU???Q???L?87P???? ?????uX?b??PW?eo?B?VW?mK?7?h&???d?Eh_g9?????;c?????L?N.16?s:????ql?u$j??e????V?6k0????M??+??E?'?????5????}?]???? +s +?0?W??tnr?&lx?c??6????s?*??-4??? ???' O????E?V???{?l??U????;?????N.?u?i?:?J%ug-??w?(?W?ev?.?2X??T?w(Y?????d9u?p????E???(C? ????K..D??G?V????:#?]7?S?H? ?Di?xFW.??^m????ZVwv?P????nr?/3??????|???d?j?C??-`??????b-?/???????0????z ???G6??? r?{Jw?tW??`? +??!?j(?R???pu?????['????@???n3E????9Z8?j? ?ZJhC??1kR\?? ??{fk~?Oz?& +?L?B?`?' `??ik +?-????pQ?????)?DZY[n???.??q^?{??a??????.????~~!???uR;?t ???N;???B?????5?Qx?1E?O????wY?B"??l?%?? 7???)]?)X??1l??????8??????z?}v????A"(w?? 3???R?T?n?????`W?T|???m"??5%~?/?E?B??F!?????????????l\I???, DPlTpsA?sB????v?????@gv?JX?U+???$OQ??????y??>????T|???????G"xw@?n=??Y,???I???K??E$??????????3C??S?U?)P?as???KB?E???! M{VZ)???g?h?'?????k???????2?n???^?1?w??!???&ll\????????f???{|? ?c??=t{?56??-????q_?Z (?Eg?????#c? R0.m?Q?cGP?^???`?????l??s?_ at 1?.? 3{?QSy???????&????y??F?V? ???^>????? ?It^?M????&.vr?L??QF/?_ r?]???F???XE+??VP??,"?)??<.%SP?$l???u?kp1x!'g???8??J?8????R?}???????7J?~eJ??7?????tu??7j*? ?S?l??rc??*[P9?"^??JW \? W???=?x??_?p9??F??V??|K??-]??U3?m?X?????N??6b^???????!? ?IR??c????Z?J????W +*?7?+f?:?Qr??!op?q?\?8??,?[??sk?y0?????[???????Vj???3?6?????na???nq?W"4?????+?d??L?m:D??????N??????&w??@??n?l??eK?s(?7??I???NR?na>?k????????^>??????Y -??6z?*.l?\F9?q(???[Br?$Q??%?i???{???E???-NqO?xf?Bvn???\]+?+???S^:?;?|??O????-??|&???)/?K|a?????!? s?1I??(G/E??L?DH*?0Y?&?o??[E??u)????????M???'??? ?Q~??/;%~???????N???X?^4ce9N[?p&?????P????t? ????QfWHH?0? e??w?a????ag*8?W?>???OM????J&?X??D???)??'?c??`"NZ?1R??)?j?.?F???~????????P??.???? L?EQ?????J??!??v?]?P7Ye ???????=_e_?eim??1???I???{fo)r?\???c?wV????PE?bF??1??t??nn??-?2???????v1?$b?G????s?,L(E???(.0g??@?b&=?S?#@?? T?3???r??(??8?=?r????7b?"????l]????G?e?N???2Q.??+?sW?????&??v?#?}??k?s?E????7????3#?????i+T?YED?` ?P}:u?????(O??v(? ? +???HD????J|?J??????U???I?Z?n??J?b"??b?E????5???X???/???x_B?-??????8&??*o?W????????i+B????h?u?C"b A??kM???S????,??wQ?rkg?p??%/?S?P7??:?A?2?7 ?UI????????f?H?`?y????%? ???????e?=o73fG???>??!C?!?.?>rU|]???n?=?h-w???H"?L4?~Qi??O.[??c???d?NWF?,??l?i{?(???:????K????ZHx???,???}?m??Lt?r#?]+?M?qs?? ?j???-?e??2S?t??%`??F???? q???-?7Q.??L??E????e???A??g???~Y??g ?/???=(c???x?C?c?01^2Q??l ??G????E??S?xR?G1H??&?5??c??/???+??m????J????L~bfN?~?R?2??? ?b?[9??? ?{ ?'>-???y0G???Ev??? ??'.?????z?C???B?~b??z?????'V #??j???'njwb>???m +????G???fA;~b6!?3?1??? f???????e~???????xq?D:??MLk.w_??R?;7*?^*5P?#wS???????D??M?_???kp7?i????D?X?6? 7??|???4?A?d?????)~????v? 7c?/??j?a??3?q??T????IH?t?B?Y??? +? ?7??????o?YK????eh???V????Q??2L???EyW|???e<]???????????@?G??i \P?b??17/?????k?O:?????Zq????]3?-?*????`??z??E ??w.y-?s??0?aST,~?D??? ??x0?:?B?\??????ps?Y?*C)}~??_???6 %???M?!??|>??@?DS?)??[(U?JRYW%??? +??J?7q5??A\???????L???7`?kpn?7?9Qd?7 O?\E?LQn????&n???????s??????!g3??|?M??NG???6T?L]?Gk??????K t????7@??9O?? ':??????#?Q=???py!wI?P??????~??ZNE?r????????\?/?9????F?Gn?n8???Y[????}q????9?w?v?T?Dypp?????m?2???? +??U??'Q?MvZ?z??a???????^????<5???D?,|~!I??7?Q?Wx???a??=??je=8?d??E??R?bY????L??N??U?C? + ?<#?0]?}???Y?7q+?'??vt+-8b??6sw*?_0?3}???:N ???6??j\?????(G??b=????.?Js at BRE???,?` +??Q???~= +B??~?K?,?>?X??~_???2~??B????y???{Z??)W?b?/????J??o(??H????????`?`?? E?-xJ(J???????Kak?fe???? ??8??e??0;e!?;%??? A???x?7o?%?\???L:%???'U???_Lf?`ri?v?\??:L2??@???$?`???`??=??z,??`r!N??P??`r= +?p???????`2j(?f?Q?U??@0??r?#(?S?I??d???d??`?E?m?L???I?8 at 1R7????"&1L=?$??L?_???zM0????`?*/??4G???wlLz??d|a5??6 ?? ??2????XO????qd?\?4?K?????0 ??3Le??I?[??e ??I??$??~??????I???Q?'??????H? &?JO0???cr?\U?????%?\L?a?l/x??{C??M??IJ??M/?????y??0?U4t????????j?? +???PD?b?s_??!????8=wDq:?1i?Z??k?F7Q?'?????te?w|U?????M>N? +|D???+??w????*????o?)?? >?q??N??Xx?O?? ?un?f??T???C????m??0P(?m??&?|???b5??@????k|???'?jC50?????? qQo=?\F9?q(xo??F?=?|?eI?VL??J ??)V??`?E????&?@? ??????RduV??#3?hQk?X?,~5]??b? ?3B??-6]??^[ ?/?&???6y??I??L????>{?J'(q;?G? ?2??RR0??uPF?7????jE?C?7?>mO?hE????CP???XS?'?]2?? ???Ic?j%??\?%?.{T???I ??*??!??p?'??o???&#??_)?V??s?D??? Q?2?????KA)???(P( ?'??l??9tPC6?-?wM?4ls???v(??8g2?{?K'V6>f????;$?\.???!??Y??2???t??k?O?? ????2 ???w?|??6g?????R???)?Xe?#X??L??P?B??I?vJ? R?q?7j???F??np?#>??h?????_???eK??k???Z)qk?@?z|?)?Y???8?????8????sT?b?a?G?q??:??uR??t????J?x;?O??B6????<8yP}./O???V/???h?0?|_??????5?3s?????????I? +O?p 4???E,?????? x??;??d??H??,5(?L=?Ylq??yn.???L3]x4???0?}*? L??g??????%???}?4M?2?r?? ???n?!?9f????_@????X0^??????Qc??N?#??_?`?????l?????r?0M???/9?4@ |$??V??"?2~q???????_?a???t?(2(f?2??Z????e??X?H??????y????4????G?<4?????S??9A???o??Z?,bB????w?????0?o ?? $?t???Xl?98??ls"?l8s???HG??????>??;e @:.1 +]?I^w=f????+?L????? A???zK?????[?????Qs?X=???Q?????#??K?I???#??%?\????*?t???>:?t? ??zd?e??&U? ????Y??jf??b? ?p+' 7J?z]??9????r O?p>3???/~??,?=???'u?|D3??;,??gPC???7A}?c,|???8??b????????p?xQ?f????r????V???S??b?U????TS?is???????????v.??x??V,?\?E/['??1D?t????!????/????#?????? ?? ?G]???h?+S??????????"?Qf? ???*???y???]???????-y???FD?w???%??F?rG???O?S??'[??F????SYk?1-??/???P???C ????La????h???&??.O??r ?q]?????3i?1???????PC?_?e??S??/????!??HN\???QNBmU? 2s?%b ?GtCE?k?c??;,qi?~??rqo??Ob?,????V>?8u?kp1xGP?????tQ `??T?h???;??+Qt??)?h?F?_?A???????????????Kv*w????U????Q???$?&?????P?B? +?????w'???)?k???????-ulA??1?91?V;???????f4????6? x~?js?_.?|??)???H??'Y??U?4??*?H?=???:J?#???f?)?I??q?? d`?W??(??????r5?j[y? +?@???xP???&?t??)& M?????2W??????K??/??W?j?fn??X??r????GP??^? ??8?2&?,????{445>:?7ZpX???????A-????-??3,???KZ!?`?CRM.????Y??,??_E'???\~?t]x<;,???f3?f?h?o?tr*>? ?S?i??1+?h??P????9?^????R??7)|???M[??A|???&?????{?N:?+Qt??????2?|Q????qg???u??}?7N???????>[YRH8??0?qr? ????:??I??Nb ?$????????d?`8y?p?t.?K/?~?z?8??p???w???b?????*?[?-?$???p{??B??(??????'??J8 6????| '??H8???NV8?_?Fk??????q"|ci?i?????p?/??A_y ??7?+?E???a'8?????g??%??????1o?????huF???c??e????7?K?a?g??ulm???????W/??@r\?#[:K?D?R V>?l??b?????????T?|???r????6{??Y?.a?????oC?Ff?9?J?? +???rC?L|?.?????;xa????cx??e?N?=%?84????? ??A!??Y????z???H;?=1???\????5 ?8?)dP|?.?D??????M???V?"f??0?<,?|??)??????y|~R????|??+ +?[???T?|? 7?}i?J?E?????? +??r=pj)?R??t^???r8-zH???>??l?6??????J??l?/?{?y?K???ii+?B?_}???(p??(?S?_(?ZO?O??&?S?L*??DH?N?????a{{"tf???D?0:?r??k???3??a??k???D??9K'B?-????y%??DpJ??#?p?_(?+M???t?ZN?^.W???g/???4?cQ??}E%Z??Mg"tX?)'dnj.?U??p?!?=??/???XW?{?????n]/???]#?}?v??????????}v??3-?r?r??????3??/???iy&H?q?/?}??8?????S??#?M???Hp??/??Kd=?=e??cT_p?W??????r??'e`PN? +S????R $???aS???????T??q:c ??]??om28M?SgWwW?0???5K?R?%e5x8?????q?t?#?DY??iN C??1?7#4N ?? ??????v???Q>?3???kpIxGV??K?? ?x?G6??j??s?)?%-??????*??? HS? ??u????,?e?(?1??*???)(??|1??i??7svy?lTGZ???n? ?O?r???sQ_>??????W.)|v??pz??5??kba??vE?5???fX?oae?h?:?9??S?"?????{|?L?D???C?16?.o?}????A,Zky =q?Tc/?F?????(?+C??????q3?x?f_?]?V?\4???e??/.=??'?5=???4??\|??&?n?[q?*C??H??????f +v??P?Y+|?????{1?!??&@{&?K?|?b JUxj(?G}E?$????Y?&?Q???? 3??D0??)n?y?c?? :;?1???Q?0kq??????A?+u??~? e???jJ?~?*??~'???c?z??NI}Zxt????2OD???vX??K*9q???[?W?~g G????}D+?c9??FVvd?x +X?+pn?IG??,?????~u?:?7?_?P}?? ???t:??<=?Sw:???"r???~?q";xB9g}?i?????|??Q~?="??*?9*??x:iE????$?d?]@???,0a??Q???6??8??Qu.?|???u???! ;?N???????C??1>G?$??@??N??ETa?g??G??r\??????/0?? ????U |W??6??,&?????'??G? a???+?H??D?^'?},NH;[?k??,N???#?,NH3[??MY?`*[?n?%*M???)???8K??(?s??Y?:???????????H~=F??w??/????"?& +5??]?Es2_?|???A?t ??H?e?(????;)??=WJ??3???1?Jp??a]BU???g??c?F???\$?h??7????9?7?*?r???Y?[???M ??i???Lf??^??K?????N?].??b????6????fb??L29N??(??K?q????6?b???????????1O?px??rF:?D?7??????H?B3?x??????H???]???63L??Q??NPF?;????.G??F??b???E??-OB??V?Sn??v??L3????/$n??fN??~T??,???K?C??)??o7?/?k???x:N]r?f.??_??8?C??3y]%????n?e????S???????$?D? ?Ra ?m?o??\U?q??f +\??n>2?????s?n??*?4/??s???24??'T???}?-U?o&??(?????fK?}?;?k?Q.?>????$9e??(?ml?? +uv?????_????4^?0?6?los?i^?w??????dn>?-= ?=[?O?????~xL??3W???^p?t??{(???>?]??Vv??i?'r}?= ?h??uZ?O/'86?W?4??1?_"???)????~~GmE????;z?W??fz{???n???|Rx?x>????s?|??????O??V T?}%??=?~???|?Nq?'?n)rL?R???w1??W??\v\=f??????V??mxgI????p?}??VN???^?; +N?(p.???k?V'Nx?]~?7Q??3??|\+g???Mc?????P?j>??x????1??{??C?C?gb??nR[???????t???ry?X?????v???b?OMl?l?u??O\? ?r?=~???s?q?? kX?%?Kw??Q? G^K?|s??????4*?F??`??? FYr????????#?v)h?~??q??1?=?He/30??eq???n A?????i?3K?P?????5?X?x?M?aX????`??WD???.?9???:??)H?w???b?Na????&?????o'Ha?<???g??!p?aN?J?no?q??~#?o????.H???VL^???w?]?3?@??|x??GnC5??Q ^??0g??T???t?4???o?!Roc(???b?3????F{2?????????#????i?R\???`??? #x7??U? +????e~??#J?q1???.?????7?D?v?????LTbfD>p????)?.?{?z8???????Q??W?0U??5?c?.6? :?)1??x?*???m*B?`???N?n*? ?? ?(??.???T$???Nq@??BQ ????B???????P}/T???M? +z?????tQ0???A?j?>F7?H???? ?? ??m???`???A??Z&o???YI?!??X?Pq ?X??????A??U??k???]?]I????o*N:?Nt???:???B?U???s?)???????{?6\?p?C?8&????_?K!??????h??7s? ?T??B?&?x??C?W?????|???1??????OP?????C???p?{??B??t?? 3A?_??vUI}?x??y?Y???W??u?????F?#?????o|?~R\?TD?~?*???? ?M??CEH?"??L???1Tt9N?G???PsV??E??l???/f?+h?{?YL?G,???g?2???3OiP?P?+?\??A3l?9?0????Q?;?D???R?]? +L8f???H?(_?$I +?Xwd???Sg?c??L??`[z,?o????CA???a?E^f?9H?)???e8?tZ?(????q@:oWfF?a??x? m???xW?????#$?$????J??9??P??cc??-?$?eB??{?????VZ?C????s??mQ?f????anQ???Tv??\?o??"??k????Z?EBN????{J?Zu?!+hpM??3W???V?? ??Kj[n?+??lO?8?'W5m??5w?^\\????9?b:??6??? ?h6&??h %????9???L???5?w????J??L ????/???Z???MA??P1?Eo!???"?@>?T?`?Cn?3`?0arq&?|Da???,fj3{??,u?? d??s?BT&???~?g?b??;?}CH?o???????L:??^p +??????(28??p????'??3t[???/???!?/Cb??@????k+0n?q?#??????X? FF?Sd6?????uXt??3?????;?%???????????e????^@??{??CE7?=??????J{??????????i????tBL U????Eq?U9??w9Y P?r??++????8?A?$?A????m????z??????jat5?? 1?Q^??(J??*9XIR?D??? Y?G#A?????a';?&2"???????!l!#rfi?2"K?3J ??2?/???!cnB?x??9?Q?a??h??8xR:?.???????=C??d9 +!?J???0???E?~r?C??(??Nq\Db??j?h5??F&??SZ>?????Q??f?:?im?A??3l???6B??*?????2 +??????S ?????;m???S?L??? ???T??)??U7??NZ???T?At?0????G??1??1???u ??*?}2?C?BG?5V t?J??v??????nN?c9Tag?U9????r ?YK???_????? +???b+A?{G,??????|??????????????B??????6?????#?`1??#D'??Gj!KI<9??#??HdG?|?4???o? +'/2?l????0???k;??? S?L?&???dA????G???0??? m]??% +?r??jAh?W?tan#?.'?L??)7?*?G ?F??x??^_h??? +? ????P????k8??I?,??????????\???M??ir??j??W???A???q ???Re<|????O3a?j&????]tk????????Lb?????3?N|a????:??????!c??U?R?????????~???u??????????,|??K????? +>??B,?Rh?4?f?W?EG??>X?(?W?}z?M?ta&?bC0?????e'?:H???M??,????$?+?f?????s'?? +??2?QA?l9?m???M$I?????? SR<AJ???J?lZX?b?Q?g5????Q???:??X?g??????Y????? ????~??????o?Z/?i?;FV????L ????????+9????,?QV?d??!?rVw*???j??Ew??????T??R??Y?~,??~?N ?C??[??? ??y#?/??????6?O?#qN>z?\w??9_??)??Pl????gW?(?p???)??}TT"???????tK#&s?????????"?? ???S\?V???>???r??q?d*?P?c?_J? ??*y?O3???I?????)????=?j?S??)?T?????_?[? QC?E?e???K??U???,?Y-Oo????s?}???^G?<( +???Y?Va?Na????%?x?2;%?f?????aj???"??M?????_,U[?'#-W?? ??x=??&?R?E&`???c??{???0O??a!???? h??pb????cbpx,??m'J?8B??9ZR??]C??=??Q#(?~????}(??2?s?(%???x??n??T?.????n??X?0/7K2R?%Kv??KK?O|???;?|??[zJj?[N??`"?tW?e??7????t~q?U??S>??r@????%a?J?.??nXJd??bw2v?????X?j at g ????)???J????F)E?V>???48???$????S[?o??*J?i?2?>Yo?I?? ?2?ne????#???????[??5??a?2? ?????7?@O?\??????????Z?Gd???*a??p??[i??L?O?????,?????? ?? ?7?8??_]?? ??[??v+#??ne??/Kb?s?=k??W???wS?g?si&???;??W ?b+??,??i?qki3?????| ???@????9~? s???|?????????g?r<"^99~?q?%?9??? ???| ??*?c&??m???w?b??????9A?&??*??\m?k?7G =?d?????ez??3?????/?e@????j?D?m???A?^V7?t?4!O sD?(W?r??Z???h^?g??Q???`XJ??????????~????4?GUI????:?+???QMyT??U&k????<+L/??cA???????O? ?r/??m????c?)gr?2???p????t?jJQ??!??b"?c??$?O????T?F7?fX6?t|?l?a??0l?aI?,?O??l???&(??/???$Q?????OU??L??C+p???????q????????w?s??{:??9k????o%{?????l???j? E?????J???=/{?9??=?T?r??h,?rX?9????????|U-\q|8?TO^ d????*_?2?\:? +?RzWo?????IP-??????>6?"????/V{j???? ? .,t7???????????2AXIR?E??? Y?G??n?hG?V 2Hm?t?W?(? ???O~??_?????K???*g??zD?f????wtu +??F?ofUP@????}?Vo?uc??z$?N?2R9B??? ?W0-Y?7????L?m?????o???????:?8????????P;,z???)?K? ???????8 9?GB?R?K?i??.kD?????1?6?8???VXuU/?`?L-?~?e? ????????F??I8(v?|mH`::?UO?? ?~EJ?]^"??W??2,Ut?n,? hSW?n?;???4 +?7?6@?F??7O?VO? 0_???0I?? #???( +DMu?B9?F?(????? #??/ #K???????= #??? #K???A???#?,???0?????H&/O??? #?|0?|!?<5L5y????3!<F]g>A??_{?A?Cw.?3?????'?????U1B-6?E???_ ?????B??cN/?9?1?????T?=*#B?!?b++?ewjh???6??I\?l?K/Y8e*???`Gbj?{???IZ? ?&y?M?6?;'???(??%-???yv?H??)Li?ZP]?OE?\?????Z4?9h??h0?9!??bB:?(W??aNQ?`=P?o?d??/? +S?4????0? +??s?A:??????????_j???P???RE???pt????#??/??>b??yL??yL???c?G?HX??r?x[?#?p??'??Go4???)`?"????'??????_?>?i>{+???!??t? +?TCk??l???????????:q??I???w?{?i?^?-8E?S??],??ew?Y??????2?????[?,Iu ???\A???'??Q??O????????T?~?BH????S??? ?\?S??"n???yAH>??I??o??Z?>??j?]F???8??????s? g;Z???o????^???|?3d??Ww?????N???9?=????a??=B?8???????_n??%??7?s???7?s_?i???|f?~???U?u'???? "`EFlC??ML???? ??T??n~??1??K3?9??s??5?????4Q*?Si???????-NF??????_M???y=??:^?r???#]>?????%??b??[????Ei??5??i???_p?g ?Uf[?z#?Z???K/?????J1H?AI?(? C??a.?vLG??)5?J??3 ?/`?;????cV[?yq??N?c?????7????u?j?uS????J???y?????>???O@?Sj???6P?dE?^8???B??JmQ??!??Xp?j"????"?j? R???n????UC/?z?/5???[????A??;? ??j??}?x?????V??_x+I{?4???`??v?f????y$?????Yb?????~8?s?)_`??k??oi?N????z7d??l?cQf????k??l)?'??&Z?obf?????4????;h??????bb9???y??{?h?G??? ???h?(C? ~g`???s???-@?D?Y?4?# [???c?,_???\??l??3?~?9??a?I\q???t4"E6D??Vh1????k?W??????????z??? q~???b????? /??f8?c3?~??cl?A at G|:??-O:q?3>???95??Vij?????(?w????zi$06?Z?8?????????;????O?N? ???N????qz??=?m1?L???-h??A???????"-:1???0(??&ui?8MX? z+!???x[??N????N/; |[??Y?-?h??X????&?s????x???Q$]?tmY?3 ??V=%??X?A1??S???c??]AWD?????(?G???u???Mz? {??X??l??lY?????A*W)w?0???????'?_??O\?_??!E???1"?M??K??O???O??c??????-???e5?~sm5Z O^??3???H??@N_??#?ETc'??p? ?y?(??e??@u????N??????Grmu[?GgY{??P???????ti?5??';5?W?d?;???Zr?????<0s";?Lu????E??l+p?;',??s? g???~????W?:???W1?'??u3???d????}??????~?p?l???b?I?????G?#???9&?????q?\ 6?go??;w=???????? ?????:X??q_d? ??3T'G??;?? ?l????jg=????b???mm~?{nCY???S??pCY to?N??X???H???h4&?????<?-?\?q;RA? ?q???>%???%?e?:???;>Zp??i??9MAk(?w??QCx?????[?{B?m?n???Yq?}???????E?+??????=?d????<"L??Z??q?7w?6??????uc?b??i????l6?S??#-4r???B.1Uy26? s????c????D??#?!???K???I?/????????f??w??a??N:o????8w?T_??m?x?)????[??6?,??;??nYw???k?e?R?;=???????/$??~u ObM?~:P?sg???=?W?Kj9?gMR?u???O<??|?z)??En??J?#!?&???R?? gW?????5??|?&?s?wk??@HnM`????$8?gv??.w??????_???%??Y??[3[A?e?2????????? ????<`??&?=95 V/???Ms?{A:???^????? +?W?M8e???uD| +m????p?V?pj+?(????????D+P|???>?A?O3?XZ?kX??;????7v'??q?????l???w?%F?'???Q,????)m??W:4???g?????p?dB?l?[?/? ????? ???g6?3??? ?????.??????? G???*??Tz? af? ?^tMA??y>????L,cf????n`??Z[p2?0???s??.O$?h?????#??Z?8?-N/!?&????8????? ?y?6Z?h>?ge?pln)??6?????_ >??U???)?#m'??4?G\gy?(?.?@??%????,???_:??GDZ????I?X?3?0[??`?i4+-8??L??????:????? q?????)%|pr?\???????M ?O????? h??Y\)E? ?!????,t??Ve;??I???O???????6????s?oq?9zj?????3b;?uF`g?????(??G?G? 4c*??c?/]b?p?;?sS|?????\?I??????}g?V?????3?:??????????Y????? ???.w??:o8??s??q?Q?aw?@?vc? +(}??_5?7?7bi????31?w?Ho???6??+?q??yz?a'w9?:#??l ?+?!Lf?p&?a??????E??s?u\g?#.??dntb?Y?Uq??yJ???????; q:??*???S?f???7??M?{z? +d??f??N ????5???iFgyS u?? ?q?G???y?????fDr??i????-??!P:???L{?????iV???._?i?????Z??????i?Pd<>1?#?? ??????z"?(???????????Y Y?j?l?6l=?m]z?S%?TE???T#C??????????7h????????s??3???LS??7N????? F ?/?Av?????> ???{???2r???v?~e???(??Xt?`????^?1M6???)???W_?.?Y??4j?????#W??^9?NQ?d}Y?d??;???}Ng??>??????9:!$K??R?????=?? ?j]zQ?:5?3???W>F6'P??mUb `m??5FP?Hs?????9#???JC$?W?????`No?Q?u K?%8????????i??W?6????y??????8?G?"PEH?.2T?\???:?x?n??????Gs?8??>?2z???????;??9>?????I ?????<+t?_9?c??c???????fj??:(???i?K??j???|???? tqtM!???????K?@?b???B???n????????=?????Z4?g???s? ??8s/?N??j???Z???j??}???????Z?a?J?f?S??a?>/?x????EMn?o?A?j?^4??5????t????j1 +??/*??Q ?????.=p???j1e@?X?D??R?ZL!?8?"8U-?!?d???hNU?vP????-???iW?x;????c???? ??B,.$)z?I?S=??1???????0`d?????|????5P>)i:???????b??I??U??E^?????G?????N?e*?7?+W$9??K??O?O?oQ???n???h?D????{<1?18??gZ??_?b,???7?q???D??Mc>???*f?X? aVa?8??N?????9s'??2??'?????x???u?)4??5???4$???4dD\?O???sD?????K]4"z3??-?Ak???|ao??R???a???@?h?????(?9?o0nY??)??*??????? ??g?[?=H ?9??_?x?%I?aO?w?jM?R??N?a??k ???3?N????s??=??H?Ao?Z+????C???6?i3??lC?b?????O.????g?i?uV?G?????.?.D???3? ???7bl?e?????o?Vi???O?p?alF?z2x)/??Mk??]X???(????P?0??&??;??S???u?N?u?????I??8????~?f{??g:??l?q?W?????0???????[?|A????cva ??C??~?!;'G?s???`?????570?h?`??{? ????2+?Z7l??u z??????pg>8??8v????e?!???x?h????r???w ???k +???Kq????f2O"????X@??jz$?????d?+???G?|?? ??;?q?Wx???xr?Z??M?d5?DyJO_?K??????:?^??v$8??? ??Y??<-?z??n??(?C?sRou??j?Q^?;'?? ?????#?P?:????????/%?S~? ?????c????F[Z?e???A?????? ??x??9?e?9???w?3?lx?K?f???};??x6iw???????F?m???EJ?N?J#?/'$]f??????z????/N<\???8*????R:5?/??(??X=[?;???f*??4?m l0TWU#e??b??Nl? w?0q??f???-??n???I[V???[^?z???WeV???M??]8??????????z???2d?X;?m@?g??/???o?PK??.???????c?k~?l0[-?i???u??f??????;???Q2J?[???=/???f????1p?+??z ??Y?????;??:8z?@?j?L??16?a???q???YG`a???e ?,?|????/?? ?????H?g?'?????r?`?X?x_?)o??wY#W ?3?X? ????qn?(????????I?ce?9?~G?4???;?\???????y-??lY? ?q?zN???*??:`??5 +h?|?;@????s????l?E??????Xy???~d??8??????n?G?P&??\W?u?0????p?X?[ ???A????????????)3Y???;F??? f?\???p7???X?c???-?1?j? ????8????? +??^??,???i0t??.3L?qQ???%7L {?1???I?n ???p{|??{??H??E??(>X?K????? +g???.w*?t?X??]O?r?F??????{???>mm?g???P?b?r\?????t9??S???a\?L???q??L????z?D????oa?d???Cc??????? ????K????x??z1 ??1\?~i B???E??????S??fF?/??????9p2??6??YB?,F?????vGMMhPsw??9w/?s???3??H??????Z=?,X{?o?????M?a(L??D ?M?a??M???So? (????"S?!????.??M]????Zo?????6?.??{t?! p??P???!??)4??p?C$???L??)M`9_???y?O????{b???B??j8???????t?|?????w?i?W????e^ ?/??P???0~k?? ?pDC?? ????f?{ax?y?^??Y?,Dt5eX?L.6dX????\#?Y?3???uN??j?Y???\?u?7????L?j???]??-o?+????i???_WH????C"7*"f??2??k28???@??t???}?g`?^????p ?A????wNU??I?????????C???]????????f?zz?~???u{?J?u?7?n??Q?~??????N??????x???k????`?D @?=E?e??T}?Pp?XgLhT?@?F?E?@4i???y ??P??K 6?NiA?_0[?t??9?K?R`UNlD??mL1?????????????h????? ???]??o^E??????/?f?1?fJE????????Q;P???c???? N??{p??`^???^???A??xzC.???t #~???h]???????8hiK?U?p??^r? ??'v??.f?(?-???o#B5??X2B??9?????j\S?RR???(?q?H??j\@O?????Lz??????XU?kk*R5?????Q??7?c?.?1??j??KT??*?l??? q??T?)??*'???$UcJ?5????????????j?^?q??_E5.??+?q??? ? ???????bY[??7.?q+?1???j?/???????-[@??-t:? N?R%?TE???rTC??q??q ?5U?????????? SR?????4????i????y+?_8?A??C??????w?qQ5ZS[Q??l?????j???o?f??o???6FU?&????xc???K5???;?v?4a?U?F?j?? Z?:@ L??r?? +??Od??????!gNj ?W*:???i?????e0?{?/??%?E???R?,l????????{G? ????@b??\L????lO>j????^+???]?k????.t?5I?E[??*,?TI&J?????d??? i"?}wx??CP??k?f???Og ??Y??3?????h????3n??q3hr@??h?]?yV?\T?x1t?KK?\*?kx????3?v??f??mC??2???????\???;v"k5??i'F?Ks??i;????}??s??W?????[???????6??6nO??r? ?wrZ?Fo?X??m????????n?g?"???????Vv ?5A?g????????l5??((1?at1?????@X??7??C???K+???E???v??^????A?p]?,???t ?h??O????:????? ?f?j???,???^?%}?????[??SM????=?%k?h<j??????t????-X?>?n^????9 2????????}? ?b??K?{???A??h???k?9i??7????bd???}??W????s?Z?w?I+^?5?q???9?M??N??}?&bad???9:?E@???4???4?k4?? Z??D???`d?L}a??1?n??>??O????????cCS?? M}?? S????W??mM?a^???gN?Q??t??>+a?????_g5M???0?sU???_????wo?;???2?????Xr?c?0m??U??k?q?f??Xg?r+???h????_L7V>3? ?z?p??}????8mK?ZF??b?h?5?Dt ??J?????O??????G??4D?89????Iq?w??-:NI????5!??q?(|?C ?)GD????1?,??E? +(O?4dk`????w???v??????L???IC?? }??b;??????h??t&????v?J????)c?M+?BhG?lc\??(????'UZ????*??q?B??j?~T?Um??Gs???"&???Tlp????.?P?3l??/mW?c????G?"n?Gy ??p?wa?J^??+'~??????V??:??????????#?B> F????dm?X?n? ??az?>bab?\}???d???!??c?c???_????????jWF????5??'?q???UOnG?L??P????*_dM??>?d??az?P????s????CI;{KCT;;z.1?s +m%??Y???-G,|},?6.In?P at g??w???????[? ??^?)?n?{??????V ??/C?sw??-!t???????/:???@v???OP?q?2?{?A??T???_??????o?????u? ??Q??? ???r????V????S???????W;^?b???q C?pd?[??????\W2?????%o-????K[?=?:9=?V????oC???}(O?2$i??,6??]&?? ?u?y:=#?Mx????m130????Nm??? ?*????????f??t<,XV?V????????PV???~?os? ?x???o???G??jS N???#L?9?3?V|????#(?z?Mu)?|??j??&e?????F??? +??Az.3???????:d5p? ?q?????? ?o??d\9xd] 4??:??i7~???iB5?CO?F???G??/?=?-?w$??'?Ro=?z???vi???e?????[?ye??s??????o?????}T7e?T????u??P9?????????1?/?}y9o??P?vsf(?s2y??vJ??y? ???x??@^?G%/ +?kk`$D??WFB at ppc$???P??f\?H????n){?? ????7?CJ?oY?2K?3`??????J_??4?|?S3%??h??k9?)??f?4.]? &???!?????x7??o???S?H?=X6cZ?y??j?xl?z?8"g?#,0??pb<????\????K?i?????Nct??_?3e%0t?(o6?k??@+?????I?xtC68?!??E?[?Jp|??!??o?\=r2?qg??>C?Z??u{k{^??P;?? ??O???[?<=?5????Ts??????s?v?i??t{f^??? ????km???_5C????K?x ??/????,??? # $??|?\???{???yh?E?J?E? ? :??1?gg= ??')?????{?R??w???????d?& }??C???k??@?t)?????#jbF+:?*?h????????"P?b????g???j?g??Fv?? ?E[~uT??V??? ??T?d???? +??n???^??h??????????}J??O?????F:???:?%? ?????"e?V????????n?b?????????%?? R???"?;??#?x?nB?r>*??I[??X?9N\??Q?/???? +c???y0??Vp?($??k'??PW. ?u?3???Ytl4E??o?H{??9?K?pF*-?%X???!&x-(????????4dg&??Bt?w????e???W??"_? ?>L?*??Y?/???^U?m(??*??-}?I.O??i|?]*?=zL*?=++?xL??*?@wM?>u?N?_PEf ]uz?"????AG7??~??t1??LA??tQ??tQ??T????"??????T6W`V+????`??+ at k??f?????coB??U?a}o??5???????9c???????? ????R[3V???????I%?kwww???Q??_??N?z1??VE??? ??s??m??ay?0~~a7+c??v???l7??eSM?``w7?)???? ? ?|? ??G??!=.?4??????]??B~??9??]????E ?{?Az#???0?G??V?vY/??q?Z?e??????n?????%,T??B??u?X6????X? f?]Wu?I??????n???tP???*B?L????dB?0??u?WVA??D?:b?n`?kO??B?????7[????n???r ??????|S?????Mgb????????????mj???X?qe;??}'?T??????>?7??g??8????=)z'???????\?V?F?90?|Z?J???.???????R?????k?aD|+??Ab????A?J???p?\8 am?????W@???C@?s? ?+?`?a?????B?'???-?a?_?z?4?????? ?????0 Y?k??????E??-V?]?????V?s????????v???V?A"?6? G?v!O$?0?g??o?%???|%[V????????M]?3?e???6??y???o????:c???o?R/TG?=??=????84???7???????v? +??&I??????b??)?6;????%???:??W#b??0?D??C????????or?n?A?#Vm???z??d?sF/?6 ??????a????????MC!?M)Z??c?%?v%??????9?e???w?????????+H??t??8?q_?G?????Gv???5?m???]2 :?oK?:?c???iY??,_t??c%?????e????????ZQ?q???~????m?4??4?????T??Q??_?/?????@?W?N?MI????4??(????~1? ???!]oN?c??3??z?x?c4"Pp:Zo??J? yX$T?s?????y???2,?????????????4?Ig?+#W?y/?_?^$K????MB????????8?9??M?Q??^$????????r???P_~????@???j-+b??????G????Q?????????~xa?M? |:V????0?j??? /???"??E?V?&y???.?HN?E?$??"??I??!??X?-n?Gn????n?av???Io%h#?Iou?[?6?3|??B~?y???_?3u2?M?vn?W??G??n???f?vG?uo?;?3?)*??????~]7???qN???y?Q???306?3?qq?.????N?>??U???Fi??TrO=?zx?t???9y ?W?????????U???M??=?????W? ???X??.???qO|rxFt???l?3??g???????Y???& Y?? ??&???I?C????B-?c?0?k??#v??Olm??B?^W36?.?eaQ4?;??0??&???L???????s??~x??#??K?9??????y??i??? ??????1???S?V????? CK?zN??C??????????{???-???}?m?v???^???2 g??'??8?+??i???$??\Q~#esr?r?a?c??Tsb>q?y0{?+?h??^?o?pu??u?q??5b?????F?K???V?Rxqm?_j???~??g??b?}?d?Ml?[???????????]*???>?/?=l???4?PS??A??????F?aSX????e?V?R????/???|?61?ss?????M?????8??A2F????U?0{?K[?0{O1???w%>[??D???????l???j?0gp? ;?X}?!?a?6??????$?????? ?`?w??;?Q?~? ?>?R?j:w???Bq??`{q??9?w0?9?/es#?\jyk?a???A!???A "?h????????W?"a??{??L? +?\\t?&????0B=?RV??M?xK??#v?!?s???Z????a??'?R&????????W??G=s????8??v?1??3?????]Al??wh??? ? Nb?y??=w????<,??????M????Sa??2?????? ????XmMxV??h%??]?????????_1?S/e?? ?[h???Y +???G?50bi?e`?s20b???+#?=r}????zj??+BU??????????.?{???e/??v??? F?????F???t?Q???????FXE?'?FF?~?|????K?2#V??00???R?F7??'#L?g??<j ?X??n???u?+/ ?p?kr?A??????{? ?Wq???H?????????\?T?0?(,|????5(??l???????%#??????<???hM?5? 7?M?V_6?e????ho?E??M* w??I?? e?????k?????sJ?;c?r ???????????Es8\?N??]??c?T??^????N? ??Q?d?????|???2w}n3??A????????P??z%R4??????_~g???????????)#=??n?G??AX?|??????TA}???~?f?F?)????5?????#N,?Xp??38?D?7?p? 3?n?????wqJ??g%?? '~?????A?;sI?$??%1Z^???n?:|???c?#}?d?/???=?~?f.t??'l;?????? u?(?NOk???W:???5??c8+?[|:?????Gj??l7>???x?????????!'N?????f???x?J1???U??t???;??F?w?=?????%???>? iS?\???????B???&?W?>@?D??6?x6 a?}??XLr???<7h???X?8????n|??C?v????J?~?Cl~a^??%??UFv?=????F???????T????Ze~??sQvs??"??[7?1pn?Q?????o?7??Q6?H?0p:oP? ?0[???v#[0h?e=??8???^?5?=E&?I??V?8?V?:s?H?g??_?Ct2/?6?:??c?f|l?.???.???}NjFC)?R3HQi?3Qa?z?p ?j?4#???f|?3???1_???y?h?Kwj??\??????????{?i??]/???)??????iS3??R,!???o????C{?'???;??N@,????3 ???nWc?!?????b???0d1?? M??l0 ?gm???"?7W ?i???????????U??J ?E?? ???eA????\\?@?????????0S78|??q??2???`????X????/?a*?4????'[?/??y+??~g?F??(????(?d????6#?r?l?????f?`??G????.c8A??X2? ??J{,*Z????v0?N!c?9???U?zN[k?y??6i??3??)?{???K?P=???8??9??y9?a????@!?+%?k>?!O}n3? |? ????3???9??B??pK?hB??4Z??Z3c9b???@Pi@?3??????&~?d????[???? ?^jO|N$??>\?.1R?}???5????????R???s????? ????t??n?%?b ! ??/?????????22???r?????C.hC??FF 7????4 +??? P?g ???n?????????L??j01?????Z?c???V?? ??o??2??????q?w??8M}??? #C??pd?N???ua?N??:nI???O????/e5???6g??8?Es3?pI0Qd?O[ik??????Sb????i??? ?&?7j?????(?SS??U!L??B??Q??8?,X??q??????f2-6?5??? IL??????q? ?*?=qbv?u?k???K`?j?a?`!?????yZ?/x??t?(u?D???%Zt9???=?\^G??Z?d+S??????? ??k??C?_???S?~&?|??? /?~pM?e)D=??)??#??s?8?@???k^?l\k?Y??K???@??=??????_p?F Z?? +-?h?TA42?;m!q.w?A?? ??????B?Ri)l)=?F?aD????,???9?????tS?)?9>??Y:Za6??????j]???D1??????D?D???h???r?y??/?????R?G?A???d?!8???Y?K?kH9y\?????{,? ~za?o`??p?l?_?????7PF??? ? ?~?ly?c-T???_8vR?TtN?\? ~?&?<0=4?y???????y?? +?]?Z????We?X7$o?Z??m??Z?????C????-6`L?_???O?-????vW???? ?!;m??h???_Rp????x????L?J???? ?C[?<9b<3%????????J??+??a^?;9@?<>@+?d ?b?-???4???u????a?[?c:W?s??1???W?*?G??=?0??)p??2?u?G?????"??.??7?!???H?I????????h?&!,l+??+?s?4??"?~???D???????64??[?qQ?18W??????&: +??i@??`??w?A?'?)????q?g +V? +?????? (nf`?L*9???$?9 ???????mO?eZG?t?x??;??N?!?c???{????D?y??!???m\?]?r????>?dm| [u??0?P-?w???St??(>Q1?%?????W??9M??qa??>???????+??? ??'z???O??q??)zl?4???? +?S?9?=?????2?^?W?*-????npxN?>'l-?N? ?V??^J??D+???V:???z?%?$??"+?"??V????????????&F??,?5.??? ??!/? ? :??rHkH??C????Nt???&?O????h?8?2?\%d?)~BkJ?ZCy\%???8??'?Z?JW??P?n???V?4Q??+??? ?=.?? ??)'Nh?l>???H\?v??y\?\??#Z~?#r???#???k?P??Y???R/?-?G4Hj?8?Q?w9?A?4?nBV`????y?A ?/x at s?????4???r at k +cw??9u*?D????????,&??q@???J'4?%??yBCN(=???b?>|????? ???? BY??}:??rvn??P?57???? ??????e&?o???:e?~????NS?????v?m?]??6???u???a ??w????Fj3?s??/?kf?k??W?&??f ??.$????B???R??b??b~?ln?[?[f`?h?B????C????2???"??m8?w?G,P??Y?d?]?1?P|??VT?????w?~??-3??f%h;+uh??VhC?V&??H??>?$??#e??piz+]?????????Q??1?a?^?????|?,?,?Rjp???>?w??#?? /?y6x? ?O?e~???O?C`??z??r8P,??_~?j??M???4s?If?2?<`??T??~???C?? ???x???/p???9_ ???R0??V?&%;A?C??Z???t l?}:???[9?6A?C9???CR tCz????????1?:?p???p/;\lF????d??y??????Z?vnj???? ?,i???????M???Z!??O?m?6?l3 M:??M?ldsX@?;?&?n?L???7k???{?]?I???k?J?h?8?%?npJ?@?C(?! l??? ????V?!?&h ?$ZF|?\;?/ ??y{???U#??p??gp-?3=\????yb?q??yw?L8??r?K??1?.I?????V+?????f??I???9]??(++?\???w??FGuA?,okI{?Y???ew??.g? ???< i6?V???j?;?X;f?s?Jc}???A?c??*???<?s????.o?????57D? 2a?Fb?v:?G'?k?I*?????????\4'`????8???u?6`}w???FF5;f????w??D\???T?0??r!9?E c???????5??B??7 ??? ????????&???j at T?.?N1Q2???~?? ^?h{\T`?o??.JZ??l???%??(??? YQ?????????????GVS??n? ?ZR;?q??x???d??m???0??g?E^?o?MQ ?;???n ???????V "?P?D@|}??0]?.\?K??? Tj t:+?kq\?Z???V]>?u??? +?os?3?>??E +???*?-??+U?{???>???+?9??dTJ??Iy{????@???B*ak??????kS9??:B??^ +??A ? +????b??6~{*?%??.Ei? N{?v??????Y?C 5'7?4ZS2u^lU??F?2??/??J?????????#?D?.[??g?? +pO\b??]??[????FFD? xz????"????7D5??D?? ?r???'????E???o~hV?????)?w"?B???" u?"?g?D??#???/o?V"X??a?H??@-????>I.?1l?c?hD???rd)??%?c?? ? M??]???m'G?ob??cD? ?@e$w)R??+%?d????Wr???V?8?A?"?i?zQ_h7?h??@?2)???@????U?f63??a??,[?/-(???8?E?e?g5%??q????q;qqyVx?? +??3? @?+????(?,?.?????&5-??w??*x??s??????`KB?*?0?!?????u????EI/?)%.??*??;?????i* ????]Y?????d ??'?E? +??H???U?????)???,d?>????im??B?+eI]??'?$El?M???!?fF????a??T U?:?v?8??k??2???W?%?1d?;??c????%?????9??\?????~? ????????1??|G???/Q?????? ?/?|????????(4?h???`X.Q??`m?[l?ZL?$?X????>u#???p???dR????v ??B:/?ZS??Y?i???3??dl!?????O?Icm?f????????????l????????,0Z???LZY?-e????]Q?o}?2?i ???H\?O?`6)1?&Da??+?[?{J?c?v????&???????.?z7?????????e?p?? CFctx???;?>?T??g;? ?????}B????q??????{chun?l ??????????:?} +A? .??Su?? ???>W?i??9??l??? N2xN%? ??&??*@0????????V?A?????';PC?;&~5???Y(????? ??????G?M??py?#Z?P?Q??Y?i^???!rvjY????)FO~sLc??m\k???atXELq?yz?] ???i ????cy???%?p?6?]@?.?i9U C?z???+iQBg?????[e??HW?o??lg?????_ETn?????1)*??????????????maOET?GkET??=?T?ro%?I??9G ???0qQy51?D?T.*/?8?????;??B9.*? ??hA???!Q?? ?Q:??p????2)AQYiEQ????Lj?W:E%0/Q???R{05???=Y??????6?VD?>?[`63??3 ???"Y??9?>?KE?b?fl*???B?2Z??,}HT?((s??<?3U NuQ(?A-5???{5??<?Q??P<????XH???M?Y_??%0?????Y?????8?ai?E??D??? ?0+?I?????????-]17??UN??O??????u{?????2??6]??S??W??TK?w6?cR????K?*??}\.? Po+??j?mi?W?U7b??{<]?WW)Qo/?)?j??~XP???ra?z?G?4J?{???DuLJT?f????&*xK?Z?nHQ??]?%0m??`?T??i,S&?z???7???;1HT???!P??I?+3?h?@?/(P??J?? +??6?z??%?g??????$???G?j? }?v?J?Y?? C?????S?:F????\?~?5?????)yy??6????[r^??7?-!Q?R???,7r??$??^y??8?L?{Z_E??|m?*????k??k?+???Y?P +???<????????Xy??B??W>?ooxjE????9?????3\?S?u?W??????0???j9\?? ???h??Pp?5???Qp??3?&%?(???[????L????-B9W?p????]?.????????}{aV??w<??3???D?0?gDG?g????+=R_???3?h???eHa|r-H??K???????8??;???0???/C$??=??????Lal!??c ??E??????-)?m??:(?????y?Q??!?H??B??p?Ng(??^F?0?_?-U??ox?J?5?????????t;?????8?.G?Oe???`?"9???????????~`??t????~???????t???]v!??]???>a? ????}a?M?6t?pW????(n0*??K???VPub,??? ???O?? ?????A????@?6??!?^??????s??K???.Vl????;? +w?e????????0nLN`?p?4?u@?UH/p]z?????{?K????^????+???????n??? ?Jp?g????????3???$`x?uL??? ?l?RS???????/nWZH9?0?"?/1~? f??{Q+tPR???? f(.> ??.}?Q +???n????88C?E!?Yp?? ?A????yN`L1?o?sR#`??~?/h#??V?$??qi+????*{U??H`n??????? ??H?????.??c?edf ??O7?d +?U1P??????P?31??H?5??"?ts?~?????ou?:F????;?D?y???? ?A????n&F??? ?ny\.??0u?????[??`?W?d/?, ???????r`??]??F!)B??*?C?tL?imF???????i!? ?b??y?Ou?X$?T?8???????;p*?a??c??L???a????"???!?????????K???????$?? ?ypf?????C?1? ? ??????e?u???W?z??f?3?x?[{? ??-&??d?{{??`?0???w?]?X???yl???????? (;?D??1??<6 Q`??c|?j H?. +?8????D~/w??{2{3Y^??*O?z`?C7N?e0???H?[???/?y?Ml$???fb|?hS ?G?Z???s"h?b.???l?????b?T??L???s?????x.?m4??h?????(??+?????j?Y!l?nx??-?o,????i3????_ED?V??%"?U0???0?+?????<;??%"????$"??<7W"?D?L????py??c?3{$i/??""?%??%"???????B???t8Ed~A?-l??}l?????Q +.?p???"2)AYiE????Lb?:E$0/?I(?????s[V??g?zib? ^d?g??F?? ?????v?v?-x???d??)?A???s?;????gP<=???J??'???+??=4iz=???^?G????Y?RJ-??????B,??Q??:?pcl??5e??po???/[?A^?`??q]h?C?zj?L ?r??????9??C??xU?1uE? ??[T??D=M??^??Mo??6?f!?,r??^?S3?%???1pMY6????|???'????ts???dY?#????i??\?1H??%???K?;??u +??/?q?8??M&?? ????qm????B??x?coP ?6???|??0'^8???yv??mZ9???xL????o?<G???????????E$??Y??o6?d}I ???v??D??????l?k~8??????e?~l???v????v??9?4??????p]?vm????a! h?uN!I??u,?S???Uj???v?;??:????4?5???;?@l???????!???t`?|"??Q?????MZo?o?G????????gP??vL(????+??Z?D?1RihC????z??Q~A????GK/??q???????>?~3???i???B$b??T????`?x?1u??????#?g???~??2?tc???[?`r????By}? ?lax????^5 +_Ue?>?@h??? 2H7.t?Ma????I????1???Ybt)??\????*??r?F??}V}s???|&X75?b?k?>?Goq?~.????????c???j?a?1??-??`?????\4???H?S???D~/Cu?2???r(?|LUf???|q}l??e8wkm?p4???P`????B?~?gN??,ayf??;??T?.??N@C;??Um?3?[?G?uLf `?\~a?c??o???d??F?|??N????VZ?(???yG^?,?u0?????'?F???@\?}q?lj)`/r??z??[??L?0???epfmHpI??jh?5?uP?r)?l]?U???ym)?N???S?????yP??~d??O???yXa?b??\4????ZE???:v????$???6_e:$ry? J??o$??K??F? ?L?8????????>???[???9????=8??{?n??' ?3???+$o`??|?????lB?%z?As^en-?o??!????M???bmBk??M??r7?9?V?9$Q? +7:f^?F??3U ??????"F*??|????`???????<8??3]??S.@?`? +?:3?Bu ?)^[pK??-he??k ??m?=H?????v???$&?????f????[?U????*??)g??A+N????mm?)g?o??41Mca??&V?q??z???U???ZG??D???2?? +?~?a=T\?m"$?]???? ??b??Ctp??f??S?4z, h???R???< ?p?IYT????$(3??].???????]j??|??$?i?Qd?+?????R???tY???@i?Q?o?????gplC???4.????4y?????B??%???X6Vv???U?{?#?8U?!?%?+y0? :8?y at J???|???IF????????:j?A??B@ ??l^D??Y8F?|?e~????T*MX?I??RpI?? +c??a.D??(???N;L$X???>y?K#?dIY?ic??X6??&??W???-l???,S??5?????I?m??;rm????w?b?_7?????????+?'?L?1>E5$PI#?!h?!??????X?? ??X??"X???[??ji?|???'eeq/??= g_<1???e? >???V??u3??mUku??1?g?0??nA?Y????8???????4e???@?Q??D????O?Aos??U1c?????? H? =K?|}co?????E??)?UD?9A?*?? ?{??&D?X1???SD??[?"??2?h4??.????/?4H?h5{Z?Vg?hD???h?b;G???TD??)??)??[??2?????@??c\f?M??1??2eI%???#Ec????)????.???????*mLG??M????W?????Poa?t`??/?ht?);?nb?K?I???)????[?}J????/?'?L?1>E5$PI#?!h?!???PE?9??K4v??/???"????(?SD???9?h????Dc?'^??'?e9???Q4ZY?VD???W?hE??"m?w??????u_" ?K??r?F???D5?w;??Ny??????^??.???pP???1|?n4w^R4?Y??L!w???? +?f5e0 S?????/?? o????5??Us??i?.?qH?/7?O ?y???2?*g9???X????x4???;??m??i?^??+?~??tb?U3a??}O +3~????g"x&D[?4????2aX?1?PGx????I|u????A??'J??????LT7?!L8?r??$??z???q? +v??EPv`-? 9??'???#K???P?|-????z??8j??:un?`?y?!??.L?q?y? +?N???'J?$?????????S? +???hB?j???? ?h??????d?g?VR?cG=????Gn?????.?Bl???{????JoV?bv=?f-???[b<;?=????FR??l1???.'??q?R??C??O?_gn3l~???:?f?)I???Z?d=? +b???T????&M)?? ^^??Ti?????{k??v???_n ???f;?b3?????-??3??\??? an?????s;CM??Osv?i4?)????^q??i7p/???$?0_???1`?????q??=(O?aj?W?D??iNGN??v/?:??Q??6???O`??? ?A?_SV??0(??k??????/?3?{?q???e???? +?s?-?@?pl?qbZ??h??? $?D?r?v?PuD-0_?qo???????R?I??N???????b?bW???t?q??mb7L4??ACz?Yd?? ???;???!?iC??g??????e???a?u?????X??Pi\{ ^|???Q?1?????x?k???L??y?,?5+??$0?S??r? +S6=j?U??'L???Z?d??\-i ?-?m{?*??2? +??p???j????v??/c\a0? p????%p?O??C?$,??d?U????4??ga}?? ??_?`????????gA?zt????Cr)????Yp|??|6q?K???a??gQ?\\????q~,??v?0?L-?V-??G??q??l?A?J??w?????}x?' ?C?#!?iG???5 f?mJ?y?????SaF +??\?2?v??-k?????c|???K2P]???=a???I?????.?(?{q???Xr???j]=? ?u?9by??T?x???>?+?3????G~????? ?fQ???n?kuf\??,??Y?wh?}???x?#t8????Z*??B& !???+Q??V???????|47????hR??-??}w????)????"?KtL?^gc?p?>??d??+???u +???.?`;g2??59LIqy=???9??W?o?Y????y????'7??"?p???R?S??`)w????#B????5??`??? +????g??;?W?!????????G??k,?>?-???X???M??z??r???????????#???v?K??s??b?7Vw???L???s????????v,??,??d]??t???&~??P??=,??c?co???q?8?:O`???R?1k??!??]??#?k??4?q(w??"?[??Gl}??????4V?R??J??8????????? +?????]?n?HH ???MC??? a???~? ??L??!??????? P???}\?u?]?|??Ek?r??q???e??ao????W??+????????-l????15??????P??O.????;!g96???: +b???e9Mw?q?j?&?"|z(?`?$ ????????????v?:""q???m?S~D?bhB_x?7#q?????6?$u?H\+1z?????!p|?\???%?mkE??A?F?u^#q?`?(???&?ZF?:,c?????T???d?>????9 ?h???$???T?d :?%?t~?p?*?%?n`[???J ,t???G????? +J/E?^ +40?Kq??8????Sz)? ?r???Qj?x)P?W/???T?m???3??3?z)?.(??^ ++?J??^ +????B?R??#?e4????R?k +?[?X??;"Oxx)?,t??Kq??w?R????^?{?!?z??k???pLz)l??o^??A??)?s ?J???JA??3)??j???M~T????????^ +??Hz)@??^ +??KQ?`???@?RX??D/???R??P?????;??m?????H?7??`?3??w?R?3?????G??x?? *?R?M???y??n??h??5:??K????cV\?-??C+W?R)? ?Nj?U_B?z)????1I5"?>??% *_???x?D???Y"?o*;T?J? nS??B?m ???7ben??j??"\3}??w5. ????;??? 3=yq???{?9J???C~z???]V?#*?>??~???|??!?? +???<&*0???X?v?j?k&T? ??X????????J??X?%?{??? h`f,?h?F70??v????n-~???Zj?|??! ????? ?`X}M? l??/?q?O?1_???? ?7?????B|U??? ?X??]? ?=?u??X[??g]?Qrv??);>X?5?'?t|`?Oq~r???1???V?gr5"A?D?9??Y.?88"?h???@??-c21??*?????"P?^????2??[??? ???? j%???m/?;??+?JE?????J??Dk???v?? ?TQ LF?py?s?&??6?G?C???q?`?/5??,??? ?????t??????D=D???7?? ,??~e`9?+???2ugV;L??? D???????9l???,U???:pys???H)???X?n?T,??j??>??W????? ?? c??cS????U?X?" `T??Lh;????$????SE??Z???s?w +?`Y????l?)X??`? \L??Yf??a?02??-K??)q1 ?????P?????+???(|???yt?z?)??d????q?p?D?Ur,??*O3?*?~?,??????S"\Q?o???f?k?(7???????*? +pE??:???W???9T?N??+???c8??o????(?lA???????+?8?qlm]*(,O?c? +f?A??|;?=??)???Fe??z? ?~9?6+)??????0?X?Zk???j???J???;???p???}w0? ,??o?$=?lR??d?;?Vy?Wu}??F????A?9?L?7?<????D??'???9wq1???}q??;???-t?!5-??????@????3???????jtZ +b}??j?Q????v.???t?"pu};?}??d??EP???=a?z:??R%{???-??~Hq??d??????????:??-????9}_ZC?Y|i?I_Zkx????8???@?8#/?/pa??x?`?j????TQ ?/2T??????`?V???Q??4T?^???????{? ???U,????????/|???9????????^???R?W s?????/G????98??}oV?? ??+?a?? +sx`?? s?? ?#?tmA ?%^????qI;???K???D^?[??G#i?Y?M?;??gz??P???TN`^;??d???_?b}????4??f?YMsa?inU?\?????T?????????*?U???(?l?%?E?????'7??sT?????YH?ms+??[fXl????9??;???b???"??^t???U??s??uW????d??9B????e?&3??2????T5 ???+???2??un-,??????a~\??T????~??????2????F???q?e?F??????????m?3?D?\?b??z5??k??sr??B5?mL?t%VkW9~_%6?l?c?????tMZ;bhh??F83????{??.????~?????k?_?j?W??S???}>?>????m?yW??H????:???_a?c+D????????n?q)fR?p1?? ????~ ?z?F???P????u?#Q???P??op?j$?]???<]!Nl? Q?C????m?????a??e#???D?~??1??F????G???^??"???n??Y??a?(,?%??????,??>?f???Xf,y????M?/l?h?Wp???5?1LD;?Q?+gA?????V???????????s.?=c?-? ?i$??H???)?? -s????j???c???????C?9??RH8?^/^?Y?? _?m?e?XV??p^?#r8f???\????I?},}?%??/?.G?ZX??y? r?&9Jn???o?6??_??6?R-]L&s? &S?c? ?4??F "D???A??1F??c5????6???Q0v?na??6u*?i??j?\Y??H???? ?-????9 +n?%7QYm?f#???uB???"x???h,??L8??1?i? JDA????Y????^?fvahi?e???u]?h8??sc????S5?:????p?-1d?hA?}??(?b??!1??C??:?|????e????Q?!q?Z 2a?F`4?hA??>?T>?2?(Z????>???]0v5}?????U????oq?? +?Y??C?????G?w?B; F????{h??C_?!?V ?3_{H9/1?ujgk? ?<??F ?D???Q??1J??{=?:6????p?\?????r?E??:??6?(???vU?J??V0?_x ???>??s?9J????????>??????t?E??+???]e???M4Z!?? ?B??1?????????o.\??s?u??!??>?9??L?9?pN,0??l???}8?(?{??)??=d+x?s??????G??9t??g??????J??P`???Q"?Z?(D?????z=???}!??V?T??V&??UB?I?-S??Y??8Q?*????Yu??U??v?2?Ye?T??7pZ??4??G0?U????a?iV??P?? +.f?0a???0y??0?4?0?4?k??D???HJ?(??>J'?{)???i??,iT9????J??#?e??[???Y?=NDa???L???? ?q??;-? .?????a???4.??>?Pl@?<'Md?F??,???2nui ??{?[]L?????h?Y? +??U?X?\??8??v??? g?J?j?????T?V??` ???????\?? ??@??t???N2? ???o?hi???????*Zyn?????i7?R??q%Q?????]??/?7a???????0?t????^?>?-#o?M????+?_>??}??D?B}RqAK??I?^??em??s??1n??v?)???V.????A?pN?1rP0?v????vS??{`????M'?e?/L????{5??D???????????jo???V????V????? 8?z??>g???F??(? *???k???t??t???9??h?????]$?4???)??????q?????^_sW{?+\?u??R|p?K?MoA??]$o? ??}??;ru|??>?_???-?F?}???AH??1:????? 8?????i?? Z?W????? ?W?P{????[??*?q???*a?Z`????X7???A??c??1????Q?T8??H? ??1??1H?s??D????HBi NI?S?c-????? ?W?P{????W??+?q???*???0??h??]o? ??1H???:??????????i??Y?????q8?O`????w???A8-}?N????J??BHwUzS??a +?jE?u?W?LH???WqL?;??(J???0????a?wWq?c??p?K????_?W_???(=?9??AZr???t?m????s??7B??9??????q x?p;????B?ct?f?jU?#??+Gi??3???T?? (???4???T??T?d?1??h???}?|?e?Q??X??u}?????c\?*???.???j???\Y?t?F???sb?i??{ v?W?8??] ?u?B???)?q?E??/??F RuKR?}??c??,?yF?Ct??A??d???U?????c\??UwU7???agW?????%???-?y?g?7@???#??;?u????LS?uKR?cR?c??4??F "D???A??1F??c5????rU?1???????|???s?k??Y ?????????sw?????G(???BU?/??F Rv??:?;H?r???cF;(???T B?? ???????D???O }?Q???B??D?G?B?t?W?0 ??V????cX2??"8??_ ???%]y ??Zm????)j{?a??0??;??b"G?s??qv+f?_L??3??tm?&,"??Xj?0??y??W?"d?gW?y?1L{??9?J??Jf?B?c? s?b????i?F??L??b???DQ2??u???AKN????1A?+?????k???'?7 +?????k?)????A?Q8??? #.???&?N@??? ???.???I??`??.}??m^R`7??+Gi??eT??yI?_?? ? B?BW 1]A? ?i$??D??#H??-c????j????X??/??3-??/?Yn)??H??$C???9f??m????O?x???| ?:s?*???8?)? ?D ?C(}??!F?[?e??g???yjA??>?V1 +Q3F??~?G??({??_W?j|???I?p??Y?-'g???M}??3Z?F??1 +m??vH?#???-??o?????-#?[N>??c??D?"?R? D??h?????r??W??_u7|?/?2r?q??9+???c?????7???Qh?(?Cr}|???_?]?-???}?m??p??Gp?#1?i? JDA????tj???e]? +?E??k??a?c?m$? ?I?U?pU?{f d??????:?=??????c%?{(Z%???U?B??Q???Q?+OU?9y?? ??,??c?*f?wnM??Aq?????PQ3??i?????&j??}???b^M?$????Vi~?y5????y?`?#q???O????????? _??W???????P????iE??,3??y??:gXW?u_??|?a]? ??h???}?|?e?Q??X??u}p??????xz?????D??b?<2?? \??9???^?[?L??>??\?? ????????;6n???e??e:e???b??b? ??IF "Btd?A??1D'?{!?q??????Y? ??Sr??V?3nz9O%?S+^?D ????9;GA??Qrk?<|????_?:1?? ???L??L?d?>??h???}?|?e?Q??X??u}?y??q??EZt???+??r?q???*??W`t??-?w?1w????c??(??G?d???e??e3???Q??v}@?'a???????,o???kP?ov??|????g???????????l{??h???S?????o???7?2}4???Z?????????hx?b?:?>??D??=f??1??"???7?:?vx????(?J????mx????3?XJw ????Dz??b??a???????:???R?xu??o?}V.?!q????????: +>??OK??h?????}"????=?kF???7??6 ?'?<`???????8O?7???V???????N?z8???/?Xg7????aO???????N????? ????D ????G?:???????e?????~??i?A???????o?}??C_?????l???uc]~kbA?V????'???7+???????? ??bsg?}????}"??g???~?T?{????:??????Zz?????zJ?5?f?.??Z?V?EiU?-??|??*[so????y?Q???K???=??????2??xj?;?O`?U?A?){B?Y??7 ?? `??3?0??E?sl?[???jR?b??n=?U0E]??9?3?j????j7|??G1???}????e???4?E??/?$??S?!???? ?=???p?e?????8? +Fu??: ????4?BQ 4y.??v?0'L??????0?,' ????J\??h???'4????????6??|?????????hLx?I?????"???N?ER?H?s?K???G?^????T??/,?@B ?1????????V l6L??@?p?eZ ~Ba?a?????_??9:u?W?,s??~?c???s?#l?s????0?'c?????8X ?~v?,???~????Tt[m?&??$????%?:?K?X???m?~??^nc;????????8???????L?T?V?v??I?M?nu8?X 7^??z?????y???? 28?u?Owrb?'??[M??l?'L?bT?v???:?%???????01|?-?AVE???>??t?5`??0m???? ??>????O=0???w??h?????????w???6????7?????7 .??e?????x?h????C??9??3u??:?=P????\ ???6/6 ?m_????2*]?[@??l`9????M _-???h %??6?ab???X?? Lq\H?'?????l?,?????/?)?&??? O???l??^????k???)=?"???i??M??d?x???9?Dy? ??????.m???s?????`?O?v;?-lF>'=?X?/??l??^m?$???$?B?????H|?wC?LL|??G????|??w7m"Bj?Z????????,lLr?????n=????W?rPD?Q?)d??s ??????NB?oF??k?.??l?9?oN??[??"k&}`????o?????yw??&g???a)7???=???+??q?9???|)???cJIs???+p'-c????-??q?\??[?1?? ??y????C?5????2R{???AO?????$???P?? F?b|??`_T#s??;W~>0.??G?cP?0?oc?x?fQ?r???ljT%?????;?c\???.<X???:?Q?~??rb?/.W??9)r?2?>??r?U?'???????l-? =}?4?|??[n.????????ji='?8=?J?????>???31??}_8B?N1?0=? D?;X$?)??????0??2????'??mb?? o?3?S???? +zo?G?b?^??b????rnJ??D'?YB?+??c??j~?|???X???8??? ~?Z??`=??mGZ?c?R??1??.?y????$ +???k????j??qKV????n?f]? ??}????????S1,~r?&D????!???!?g? ?-??&6?e ?\w?????4???Tf?????Lu?V??J??4(?????z?(?? v???????????l]T????.?6??nKp5??S??8_???3???/p{=@?M???u? *g|?"????]??9p??!6?2????e?b?D??"?[|s?[I??Z2L????;??;?Y?????l? +???Q?y??9p ?>6?Q7???g{???:4????????S??1.??W?1k +?I????&?????*?Q???j??c?8?r???????u???????qO??H?e_?^?7c?ur??Q????? ?\]Hz?'??9?rt[rF6????E?xE=?E?4M?_s??5?~?\y??}?v+????S|??? ?)? ?????p?P???[7S????~1?IC@???4???s?? 1??8??|0???%?K?:? ?;??&1?NC??Q?N?a?-%??o:?)??l?K?Eo? /? #e??&#???|q??????j??#??+????2U? +/91???Q?eV+pY?.v????b?NU???'oa?N?K??*?|U??r5?Yx5?#??P11t?b?%{??U0]???j-D?L???cn??.???iI???lb? +?JH?!'?(?1M?t?Qa??????? ?Q???]??i;???&q?? +?M????Ed=l(M??8??/?Eso????{??b???????Nc?a[n.??1??i??6%????|?N????4\????????n? 3??i???NZ?l??Q&.????nw ? ????v[?>??*w??;?m?e? c?A ?1???a?5I?@???r??r?????)7????}k{LD??T ??)?n???@??Q????t{7?xS*???E(SfX\S?:F?L???? bT?k'gA?+^???pA??wqmG?0??)!M?????????q%?c[????O7 ??????(?/??+?endstream +endobj +632 0 obj +<< +/Producer (ESP Ghostscript 815.02) +/CreationDate (D:20060723202022) +/ModDate (D:20060723202022) +/Title () +/Creator (inkscape 0.43) +/Author (cfbolzcfbolz cfbolz) +>> +endobj +633 0 obj +<< +/Type /ExtGState +/OPM 1 +>> +endobj +634 0 obj +83385 +endobj +630 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [105.602 750.9806 118.6329 766.9208] +/Subtype /Link +/A << /S /GoTo /D (page.47) >> +>> endobj +629 0 obj << +/D [627 0 R /XYZ 74.4095 738.0292 null] +>> endobj +631 0 obj << +/D [627 0 R /XYZ 117.7423 210.6604 null] +>> endobj +626 0 obj << +/Font << /F26 180 0 R /F31 192 0 R >> +/XObject << /Im1 171 0 R /Im3 618 0 R >> +/ProcSet [ /PDF /Text /ImageC /ImageI ] +>> endobj +637 0 obj << +/Length 3303 +/Filter /FlateDecode +>> +stream +x??ZI??6????m?*?! p?9?????Rq???C?E?%?\??????m?&vR} ?,?[u? ?/????A?R??A?G??yvg??}E???s???_}%?P?J'???i???R4??8 ?v??{???y????&H????????cam?i?a?;l???M]??S?*?nEk?b????Zf|m????????_}??]?? ,???s??4?V???^????|???Y?K??????u;??/3+?????a???qi???a?'*IW??l?J???w????x????4Gs?^ 9 +?d?*+_? ?q??2???????s?$5o???P?????wM???{??a????f~? +???a gD??}v'????????*"??n6??F?????Z???=-V???????Yh?m???A??P?7?3????,j???m]}???8+?I??i?WZ~?;??WPr?8}"???9??0??V???h,?^???p5???Q?5d??E??????Z&?]/????qeSU????gf???`??D?i9????"(W?????a???h03m"J??????? ?[??$?a??Z#l?? }????D?|???f?]c??1????R"??D????Q'??X?C[??^????I????RG??|`v(??D?*U@??????o?$ +1?e9k?0Z&??^????????h&d?l??? ????`??m0??%*??ikm??????[?O ?????,-Q????j?s?]&~X???T??u?=$? ??t-???p??? +?v???^w??????*?Keg?1+:^zY8??~?|??U]???1q???K?? ?H?@?_???z??H???"=  }?d? u??*?5? hC?/%?)??b?|??=????????WkV????(?????? +?_?=?W??+?z3?x?Ko?C?0wu??5z!Y&????????A?`????|???bX2?a3?`Z??g?7??]???1???W?e???k]@???(JX?H?& w.??????~?????w?R?N??R?Z?ZuN??ck:????kp^S8p!??1?????n????R?t????b?8??)"??,?i??@??2pc?e?q?j?u???L^?>?n???@?? 2X?n4 ???R7J?Y?????%|9???l??.??z6l?UjF?c???c??????*?zS?????:? ?5????)??g*????k???$4?L??????b?@}?J?aW? + 'Q)?????: ??8AI?5T&?Cm?*I? s???GQ?9?? hWZ?b??????]8??H@#%??X?X?T?????]H??z?$??-?K {?{4T,C?? ???$??Lm;?3_???.?z??Z?B|?l?uW3???8S?M9J? +"q????'??i???? +?,q?6?????P??u?????r?M??"h??!.5??Z?y????*?1?Y????W|1?G?s?????/m)#??V?%???i2k+.4e*M_ k?9A??ea )) ? ??6?'?D"?????]=?Z??{q(?+?Jy??d? + ????F ???C=s?W[????p??`?hI????H~^??, Z]???V???????$?Nn?????j???P?Z5=??8?fu????????(?F1\????L?iB*??UB? ?(0?+r??[T?fzyc@?U??2???_d?q@Fnd??????&1Vd?uN6? f ?????|????]3???????&=?MB??\F?T0 ??o|n??Q??Cg???h????+=??-?O??>??c?0?t?Tz,???7???W'?????B?????a+??? _?X???u???q-w????Bn/*????Iu&p?????????????z?> endobj +639 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [105.602 750.9806 118.6329 766.9208] +/Subtype /Link +/A << /S /GoTo /D (page.47) >> +>> endobj +638 0 obj << +/D [636 0 R /XYZ 74.4095 738.0292 null] +>> endobj +640 0 obj << +/D [636 0 R /XYZ 74.4095 630.521 null] +>> endobj +154 0 obj << +/D [636 0 R /XYZ 74.4095 611.5368 null] +>> endobj +635 0 obj << +/Font << /F26 180 0 R /F31 192 0 R >> +/XObject << /Im1 171 0 R >> +/ProcSet [ /PDF /Text /ImageC /ImageI ] +>> endobj +644 0 obj << +/Length 3044 +/Filter /FlateDecode +>> +stream +x??[?o?8?_??? ?,)???=??k??E?M?/mdY?u?%o$7???7???K?? +??S??h8?q8$Gb??O?|?????n??????A????/? ?|?}T???????*???GY?di?}F?????}??Y4_h?J??*^??$???????_K1 Y??2??-?d??}?z????;?-?^???????a??|??????c???????B???60f?)?T????~?3Oz???l?p?z?i??g??WI?lW?== m?.???VJK&%@??? P???3???2\?2??q!TH?????l??Uq??????7?X? + ? +??0F????|????????=?@0??JyLi???d???N?iz????,??Ho???Z?zt??A ?Y?X???Z?}Zh????@??:?i0??(xy}sh"?L+??F??y ?????*???B???Y? 7??y??2??8??aO4c??? {??*}?p??e?'???????>?-??? ???0?? +% ???Y^=V?"?PW??i?bh\?C==?w?!??e|????`;ee?!?D?'dz jZUIN???.5?L??.??????[N?^ ? ????T??2??t^?}??DifoV?g?????>?K-?+m??\???dG?d????dO?"???[?]??T??iM{W??1?iw?$c ???&??y?Kj&?P??? 6rA??6?WG?d?U?WO?"??|o?, :?-?fss]=f?t&??yC???(q:?h?i????Kq?AgT?:=?8?k'4G????Xm;???u?`???j3?'???[?J??p ?a? =??rei????Q?????s?????C1%L???????????8g?=?x;~?8???l?????E?I??Yf ??????????:???.?? ?m?~?uT???X?8pq?wz?n??gr?????Q5???,l????? ? ??Os??6kh?9%???????1F??]?!v?)?m*%???}?i]??Q}?{<(???=O???:Hz?ei^??4?=??vny?Xn??.J????1????#??i?T?????P?> o???&s??*????#????i? +'?t???H?H??m>EqL???h?Q?=?z{?4?|?G.??-?????h\?G?V?ia??lbq??Q=C?i??@{?)4P?Q]hL?????x???J??@? ??????g???S%&3?Yoa??O< V?1????x?K????;?f????I}L?????A???q?@?L????cmM?i ?r?*??*???6???9???g?GB???J?}p?9???8~??????LK}??????n??N??endstream +endobj +643 0 obj << +/Type /Page +/Contents 644 0 R +/Resources 642 0 R +/MediaBox [0 0 595.2757 841.8898] +/Parent 641 0 R +/Annots [ 646 0 R 647 0 R ] +>> endobj +646 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [105.602 750.9806 118.6329 766.9208] +/Subtype /Link +/A << /S /GoTo /D (page.47) >> +>> endobj +647 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[0 1 0] +/Rect [113.7426 661.2123 139.9839 670.7465] +/Subtype /Link +/A << /S /GoTo /D (cite.VMC) >> +>> endobj +645 0 obj << +/D [643 0 R /XYZ 74.4095 738.0292 null] +>> endobj +648 0 obj << +/D [643 0 R /XYZ 74.4095 648.2908 null] +>> endobj +158 0 obj << +/D [643 0 R /XYZ 74.4095 629.2174 null] +>> endobj +649 0 obj << +/D [643 0 R /XYZ 74.4095 574.8404 null] +>> endobj +162 0 obj << +/D [643 0 R /XYZ 74.4095 557.1294 null] +>> endobj +650 0 obj << +/D [643 0 R /XYZ 74.4095 518.9864 null] +>> endobj +642 0 obj << +/Font << /F26 180 0 R /F31 192 0 R >> +/XObject << /Im1 171 0 R >> +/ProcSet [ /PDF /Text /ImageC /ImageI ] +>> endobj +653 0 obj << +/Length 2978 +/Filter /FlateDecode +>> +stream +x??[Ks?8??W??TU??Mr????v??{bg???9?%qL???????x??D??ntH?R?@?????`?d???q????iH??f????X?QM4r????=?r at 8b\???t`?&?!?@???w?|?<?{'?G????q????2?6??KL??z??,K??\?1?wC???(/?h8^???8.?I\????>?=cd?P?0 ?C!?}?? ??^1U?G?w???H??B !?0kW]?3K???BC?rh5l??W????I&?-?[?o??qm????1??I?dq?R*????P?f?h???H???? *I????????I2??????T0*????b?,r?? ?????U {????$?[-@?P???j??????tq?D@???bX???A,??/gh?????????;(???XR=??? H?>?{?O???????1??2J??9?~l????`?}f ???M0o??13p2?.?.??o?6f?.g???8)m????/?I?cGvC7??????VYd7????WYf?;2K???\"s}???=nq0?D~Q?>/_S=??/??~@??z?m????q???c:???p?? ??M?V???U???/?L??2?v?4?7??z??6'{??\j-JD!@`???F????T????*?????rK?5w?K$}?^??Id9??s???nv???_/Z??rH???~L?f?=2A??G?dLVU???8?Ya?M?|V~???4??`???????????:?Q)k???$???w?[????p'{R??????????psf;?z%l??J?????NBbT????~E?L???s???(??e?M??i7?????-?fbO ?? ) lz??w???c???X?? ?\I?????S?5\&?????W?A e?`jr??b?f&?????z????O?-/?t??CI??a?b????%??lr???U7:???^ |lH8??YR)T??? ????~?H?!Fa(?$? +|??]???Zs)?_???????>?p|?e?P??L?TEc???:?i>S{?????MJxWe2n+c???Rv????!,????????????2 ?oTa??? y?G?????T1@?;?????*???AP?????4 xA?o?=fq?z?RS?|??X???c?c??*.?c???R92/.? ?????S?K!???U?21?l??mR]I?+???+r?[; J}??X@?n)8??H? ?,?? ?!I?????x3l????> ?0??m?+?~????gj?]?????=??\?n?6T???????????m?????u?*??????r!dE? ??qS??F??A?k?+[?*?Q??"??F?r?G 5?????????I?}???)cg???XWh???1?? ?????k C0Kr ?,??7e )?(V?>?4?W?` +;?En? r?8I&? ???\?k]i?5????<?Ws?z????J?P???? ?t????J?????+???v73??i?5?=o[??Z??Y?b????Ie??b????R????e??"O#?R&????SC?4?#??=X2e?? ?}1>?1?2?!?????^O??J??q?So???0=[_{?????!??m?9Rn[????w????B?6? \00E??{? ???????WI ?T?n??}?N*XP_?" ????%??BR?'.?T&.?__?%??}???z????{#?????p at v?N8T???P?p??8?x?|6:I?3?x^???*?!Z>?W?*j?Wu .-??[? ?=?i???z?7?????J???Qu??B?V{F2?G?E????*????[?w+?e?[?????WE???????? !??06?Ci=$S!???u??&jT??U??u???? +w???uzR??Bk?_:?]?????Z??3,?k.?Jw,z?w"n??z?endstream +endobj +652 0 obj << +/Type /Page +/Contents 653 0 R +/Resources 651 0 R +/MediaBox [0 0 595.2757 841.8898] +/Parent 641 0 R +/Annots [ 655 0 R 660 0 R 662 0 R ] +>> endobj +655 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [105.602 750.9806 118.6329 766.9208] +/Subtype /Link +/A << /S /GoTo /D (page.47) >> +>> endobj +660 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[0 1 1] +/Rect [277.226 231.4241 494.4585 242.9209] +/Subtype/Link/A<> +>> endobj +662 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[0 1 1] +/Rect [165.5668 167.6632 278.0837 179.16] +/Subtype/Link/A<> +>> endobj +654 0 obj << +/D [652 0 R /XYZ 74.4095 738.0292 null] +>> endobj +656 0 obj << +/D [652 0 R /XYZ 74.4095 619.2745 null] +>> endobj +166 0 obj << +/D [652 0 R /XYZ 74.4095 619.2745 null] +>> endobj +657 0 obj << +/D [652 0 R /XYZ 74.4095 577.0738 null] +>> endobj +658 0 obj << +/D [652 0 R /XYZ 74.4095 415.6212 null] +>> endobj +480 0 obj << +/D [652 0 R /XYZ 74.4095 409.83 null] +>> endobj +659 0 obj << +/D [652 0 R /XYZ 74.4095 377.9496 null] +>> endobj +540 0 obj << +/D [652 0 R /XYZ 74.4095 358.0243 null] +>> endobj +579 0 obj << +/D [652 0 R /XYZ 74.4095 326.1438 null] +>> endobj +493 0 obj << +/D [652 0 R /XYZ 74.4095 294.2634 null] +>> endobj +541 0 obj << +/D [652 0 R /XYZ 74.4095 226.5174 null] +>> endobj +661 0 obj << +/D [652 0 R /XYZ 74.4095 194.637 null] +>> endobj +550 0 obj << +/D [652 0 R /XYZ 74.4095 162.7565 null] +>> endobj +262 0 obj << +/D [652 0 R /XYZ 74.4095 142.8313 null] +>> endobj +516 0 obj << +/D [652 0 R /XYZ 74.4095 122.906 null] +>> endobj +517 0 obj << +/D [652 0 R /XYZ 74.4095 102.9807 null] +>> endobj +651 0 obj << +/Font << /F26 180 0 R /F31 192 0 R /F34 291 0 R >> +/XObject << /Im1 171 0 R >> +/ProcSet [ /PDF /Text /ImageC /ImageI ] +>> endobj +665 0 obj << +/Length 3522 +/Filter /FlateDecode +>> +stream +x??Zmo?8??_a?????Q????!q??m?d???????????,???n??? g?[V?5?r(?3??9?O?e+'?F? m????bs??V@{w"?gb?&m???????????wG_G?c?0?M?????????????x???u???i??c=?y????gUi????&???????????|8 ?M??#Z??aAX?W?=?|?_K8??E?; +???n4?-4?4?????w?tY??k?v?yd????c???C??IWxv?d????a??= r?^ ?????????e?????fs ]???%???-?8???QX??j?????b?L?Y?]????sZ@?ZTEc 0?u J?S???X??x???'@IG??1?EK??????^$??I??Q;?D????]?t]L|,l?q?4zah}????T/?Du?~l??+@1cqF&??c??Tv?W?e?k??Kc?????v`?`9$?????l??????,???? EXCa?"Wh???oca??~?A=?C???XI??.?'??@?/??o?YY????n???%??????Q'?? ?H??8???? ++gOK???|?`?\[?V:?F?V???!?Z?f?'T'9s=???g??U????KV.P?ve?dY??M?){?????n;?B??mI?f:?hr?x}~x????=H?$? +?#^:$Ki?}"q ?P?a?????H? g!?J ??!!??:?/D=R{ ??,???,ZO?|??2??{c0????m??/?mQ?? ??n?5$\dl}?9?d?m ??{?,:??-????h~?1? W_?4??u4?=a?Z[?{?d?5d??4?U??N??????b??U????B???j?*2??p?D???B????X?N???+?????T???vu?h?)?g?B????5`T???j??a???????@pof??|?Jv}a?Z.d?????)?_??5Q???s?) 9???.l?T??^? +?iN???k?+???0?{x?k??<%?:g????`????????.???_???0????????????x???M??$"??????>5~wk?\i?k?????D@?2q???:??? ?@t=&??5Am ???V6?*??@H????? ??5?@?E?????6$???A? ???) ??-??"_; ?b???? ?8/???y??pM??????[d4??N?3#;C??4????P??v?????????????_?|[I???b:? ?D??r=;??!? "????m?k??[?????}*?-?t?*??len??V99?????{-?D????:?q2?????g???(?I?M?';O?S?;??????R??UK??]$NTd?GJ?????? +??endstream +endobj +664 0 obj << +/Type /Page +/Contents 665 0 R +/Resources 663 0 R +/MediaBox [0 0 595.2757 841.8898] +/Parent 641 0 R +/Annots [ 667 0 R 668 0 R 669 0 R 670 0 R 673 0 R ] +>> endobj +667 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [105.602 750.9806 118.6329 766.9208] +/Subtype /Link +/A << /S /GoTo /D (page.47) >> +>> endobj +668 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[0 1 1] +/Rect [165.5668 683.16 521.8625 694.6568] +/Subtype/Link/A<> +>> endobj +669 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[0 1 1] +/Rect [165.5668 671.424 291.384 682.7016] +/Subtype/Link/A<> +>> endobj +670 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[0 1 1] +/Rect [165.5668 388.4851 429.0856 399.7626] +/Subtype/Link/A<> +>> endobj +673 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[0 1 1] +/Rect [308.0107 93.3717 435.6409 104.8685] +/Subtype/Link/A<> +>> endobj +666 0 obj << +/D [664 0 R /XYZ 74.4095 738.0292 null] +>> endobj +617 0 obj << +/D [664 0 R /XYZ 74.4095 722.0889 null] +>> endobj +593 0 obj << +/D [664 0 R /XYZ 74.4095 666.2982 null] +>> endobj +518 0 obj << +/D [664 0 R /XYZ 74.4095 622.4625 null] +>> endobj +542 0 obj << +/D [664 0 R /XYZ 74.4095 590.5821 null] +>> endobj +580 0 obj << +/D [664 0 R /XYZ 74.4095 546.7465 null] +>> endobj +581 0 obj << +/D [664 0 R /XYZ 74.4095 514.866 null] +>> endobj +595 0 obj << +/D [664 0 R /XYZ 74.4095 482.9856 null] +>> endobj +476 0 obj << +/D [664 0 R /XYZ 74.4095 415.2396 null] +>> endobj +494 0 obj << +/D [664 0 R /XYZ 74.4095 383.3592 null] +>> endobj +578 0 obj << +/D [664 0 R /XYZ 74.4095 327.5684 null] +>> endobj +671 0 obj << +/D [664 0 R /XYZ 74.4095 295.688 null] +>> endobj +322 0 obj << +/D [664 0 R /XYZ 74.4095 263.8075 null] +>> endobj +479 0 obj << +/D [664 0 R /XYZ 74.4095 184.1064 null] +>> endobj +495 0 obj << +/D [664 0 R /XYZ 74.4095 140.2708 null] +>> endobj +672 0 obj << +/D [664 0 R /XYZ 74.4095 108.3903 null] +>> endobj +663 0 obj << +/Font << /F26 180 0 R /F31 192 0 R /F34 291 0 R >> +/XObject << /Im1 171 0 R >> +/ProcSet [ /PDF /Text /ImageC /ImageI ] +>> endobj +676 0 obj << +/Length 2931 +/Filter /FlateDecode +>> +stream +x??Y[s?:~?????gjFI]??>??K???????i;Eflme????d?%??,w:?$@??|???> +$?n?F???E?(Y?????=??gR3M?\??'?o<?%??F????e" @?1?9??_????e ?P??????$??4\?w?y?eD??[O?V|tY??u2?k??,???uE?+8#3??7w4?????B5z??`<W[?H?3?`i????N?2[?fj?&6?=???k2`(???3,?U$??? +Y?I????R?"? ????A ?\!?V?!??|O???@ +?|??aj? ?^_b?;;?Am?4??????r?m?:g?}??H?i?jc?wp,t??*? ?>?"@??b ?N^-??h??Ze?Y?? r?y???6??j??DS ???Z?')??%???v6??????<p?]8E%???E????2?&??T???f?w???U?:?#~????????z:??Cj[.??W??|[1(??a"l???ZyOG=?a???H/????*?s????????????p?????X???=?-D|~~s?P??r???????? ??;/?????Ca???d W??a?hK???, +??w?]??^q???o?????4?????-???z?/???2?(?#?*/?????u?????h????????n?dD????(??}n? ?? ???_76?@b????UA9?????9???????????&?M???e?R9??8???????9Q????*u????B??%?|!3a?+}H) \(?,?@;?~??????1?e?/n??':????[7??y5?????g?v? ?w0???t????1?>??y???An y?s&?????{z??????bZ?zF?L?0:Z?Y?I{B_????*H*?zr??n????l?+??,???????/????>?2???l ??H???????o.????vOoo ?????sI]5?k*?8Y?~???_?? ?$ +?6????!??v?7????rAx`B?j*?Y=?I??Jmz?. +3?46j6? /6?&d&6?[i;??(??eC???o?Wo?U.??a?M5/?? +???????iR??????-Zs?d??" $????????$?-??#?G?t?????=a??j???zS??X}??{????*JW?V:Y?>n????~}??5j??#|?=??Q??????N?|BKa?1???:????=??'[endstream +endobj +675 0 obj << +/Type /Page +/Contents 676 0 R +/Resources 674 0 R +/MediaBox [0 0 595.2757 841.8898] +/Parent 641 0 R +/Annots [ 677 0 R 678 0 R 680 0 R 681 0 R 682 0 R 683 0 R 684 0 R ] +>> endobj +677 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [105.602 750.9806 118.6329 766.9208] +/Subtype /Link +/A << /S /GoTo /D (page.47) >> +>> endobj +678 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[0 1 1] +/Rect [282.2871 659.2497 488.4812 670.7465] +/Subtype/Link/A<> +>> endobj +680 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[0 1 1] +/Rect [290.8748 591.5037 486.0304 603.0005] +/Subtype/Link/A<> +>> endobj +681 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[0 1 1] +/Rect [327.8158 516.0069 458.6733 527.2844] +/Subtype/Link/A<> +>> endobj +682 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[0 1 1] +/Rect [165.5668 496.0816 364.4586 507.3592] +/Subtype/Link/A<> +>> endobj +683 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[0 1 1] +/Rect [321.9983 364.5747 467.431 375.8523] +/Subtype/Link/A<> +>> endobj +684 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[0 1 1] +/Rect [165.5668 252.7739 578.4147 264.2707] +/Subtype/Link/A<> +>> endobj +197 0 obj << +/D [675 0 R /XYZ 74.4095 738.0292 null] +>> endobj +481 0 obj << +/D [675 0 R /XYZ 74.4095 722.0889 null] +>> endobj +679 0 obj << +/D [675 0 R /XYZ 74.4095 654.343 null] +>> endobj +474 0 obj << +/D [675 0 R /XYZ 74.4095 586.597 null] +>> endobj +390 0 obj << +/D [675 0 R /XYZ 74.4095 530.8063 null] +>> endobj +301 0 obj << +/D [675 0 R /XYZ 74.4095 510.881 null] +>> endobj +563 0 obj << +/D [675 0 R /XYZ 74.4095 490.9557 null] +>> endobj +478 0 obj << +/D [675 0 R /XYZ 74.4095 435.1649 null] +>> endobj +475 0 obj << +/D [675 0 R /XYZ 74.4095 391.3293 null] +>> endobj +271 0 obj << +/D [675 0 R /XYZ 74.4095 359.4489 null] +>> endobj +477 0 obj << +/D [675 0 R /XYZ 74.4095 303.6581 null] +>> endobj +674 0 obj << +/Font << /F26 180 0 R /F31 192 0 R /F34 291 0 R >> +/XObject << /Im1 171 0 R >> +/ProcSet [ /PDF /Text /ImageC /ImageI ] +>> endobj +357 0 obj +[170 0 R /Fit] +endobj +685 0 obj << +/Type /Encoding +/Differences [ 0 /.notdef 1/dotaccent/fi/fl/fraction/hungarumlaut/Lslash/lslash/ogonek/ring 10/.notdef 11/breve/minus 13/.notdef 14/Zcaron/zcaron/caron/dotlessi/dotlessj/ff/ffi/ffl/notequal/infinity/lessequal/greaterequal/partialdiff/summation/product/pi/grave/quotesingle/space/exclam/quotedbl/numbersign/dollar/percent/ampersand/quoteright/parenleft/parenright/asterisk/plus/comma/hyphen/period/slash/zero/one/two/three/four/five/six/seven/eight/nine/colon/semicolon/less/equal/greater/question/at/A/B/C/D/E/F/G/H/I/J/K/L/M/N/O/P/Q/R/S/T/U/V/W/X/Y/Z/bracketleft/backslash/bracketright/asciicircum/underscore/quoteleft/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z/braceleft/bar/braceright/asciitilde 127/.notdef 128/Euro/integral/quotesinglbase/florin/quotedblbase/ellipsis/dagger/daggerdbl/circumflex/perthousand/Scaron/guilsinglleft/OE/Omega/radical/approxequal 144/.notdef 147/quotedblleft/quotedblright/bullet/endash/emdash/tilde/trademark/scaron/guilsinglright/oe/Delta/lozenge/Ydieresis 160/.notdef 161/exclamdown/cent/sterling/currency/yen/brokenbar/section/dieresis/copyright/ordfeminine/guillemotleft/logicalnot/hyphen/registered/macron/degree/plusminus/twosuperior/threesuperior/acute/mu/paragraph/periodcentered/cedilla/onesuperior/ordmasculine/guillemotright/onequarter/onehalf/threequarters/questiondown/Agrave/Aacute/Acircumflex/Atilde/Adieresis/Aring/AE/Ccedilla/Egrave/Eacute/Ecircumflex/Edieresis/Igrave/Iacute/Icircumflex/Idieresis/Eth/Ntilde/Ograve/Oacute/Ocircumflex/Otilde/Odieresis/multiply/Oslash/Ugrave/Uacute/Ucircumflex/Udieresis/Yacute/Thorn/germandbls/agrave/aacute/acircumflex/atilde/adieresis/aring/ae/ccedilla/egrave/eacute/ecircumflex/edieresis/igrave/iacute/icircumflex/idieresis/eth/ntilde/ograve/oacute/ocircumflex/otilde/odieresis/divide/oslash/ugrave/uacute/ucircumflex/udieresis/yacute/thorn/ydieresis] +>> endobj +611 0 obj << +/Length1 1606 +/Length2 8282 +/Length3 532 +/Length 9134 +/Filter /FlateDecode +>> +stream +x??weP\??-??o?-?]?w??6?H????5? $@???=?K ???[??oK1?t????)? ?q?l???k?-?C?k??rt??O?Z?O at w???k?ZG????p??!i????????????=?d?9q?????? Q??9d??^,????`"?.???3"??p?p???7????vU)4????.???<{?&??I?%??4Z2tP??j?'?K:ry?oB?? +gW?=/??r?v F?5"&?'/???s#?Z???#%?? ?x?r???????&P??j??sR?J?????.X??? ?7???6?Km??????,?{??3H??l????????[?Ep?????si?]??aMS???+?o???"p_??? ?????~>S?#\?e?T +0??)AL?????mNu]N??+?0$'H???Jdq[????Z??Bw??W??B$f?????v?B?)?uu?0??? ??E?p??X??9?T??GG?N????Y?J?{-????i???t?????2?????Iw-?3 ?w"?{?wR??uC?x??????U?"??F??g?6??m??K??^? ??? +?????M??x?X??l???bd9 ??X???J?N?!????M??'7L??T~??X??F|o?a+??1??M?;(???3J?~??????~?&p@?'?????4???^C}??G/X~@?]???{???Q??E?[[????S????0?`????????QT?7?t?=????????C????%m"?????Q ???? E???`????7????;c6C?l??g?K_??o{??????????Xb:d_?b ?(?%??U???\9j>????????2M??????5e??{(??^???{?f6? ]d??l?6W?=kt8[-\R#?????1? A????Y??Q?MN?\A?cn??Z????q?u;????;???m??????????mlo??2$????h?ro?4??H?;'?? X?$??? ?}??i??????????Hn>|?T??e????w?????? S???9??R?????2{3?ZE?? ?1VY???ip?z!??$UM)??"?x}[???????0A??????*o!?g???????? ?SDy ??[??M +>??h ???????????G??r/?s??????x????7??b??%1?v0??8?\#?????????????g??????*q$??????T??????R?R?M ?*??S???|??? Ym???E.jh??[?????[ ?%)?? f9??D~?7??3}???h?.??` +?????Yb??;w4?o0*{'1?B?????P_?n$?o?x$1?{p?0???5>s'T??G?XO??.?1/?U??%EG?,ux??#z??u?0U????y??????A???x?g???????i,??/?du?g????}??j?????yuMw??>?*?AT?si G?Z$j)G??????@???YW2?M*Tn?OuL9???0????????S%$?fRp???7???Ec???9??%cs???????r.3x(????B{?T???e????cI?k9?YCO?>k?\_`*?????(????+T???&|?Cb1????? ?V;e??%> \??a9? ??M???S[o?m??3g??'?XS?9?QD ?????`?H?@]?z?n`?m]?^?????m?m??.}??????N?wR??#\8???c??f&??}??g]???Q?UH??????K+?'y???Gj??=+?B? ?a?c-w?U????? ?ow?>D????????VY??(? +??????o????n?J????+??? *???{7d?}?a??????_???"q??kS??S???`=?aV)??? ???????vs?@??L?c??Q?J????|???\??^??}?H?~(?qx?F?KB??m.???w?T?? ?? W?~?Pn??^???j????K?Bn???????S?`?Z?1?s???c??_459???m?n??^D%?>???)d???/x??r?????W?N???^=?j?????? 9v??@C=?u4??Le???#??? 8 |?!u);????t???F???e2????g??xDbp??|????? e?HL/6?.?{8(r?t9<%??qrJ?0?f???F?V?W??c6vh?????5k?>_UB??e??A~J??=(??oNW7?mfh?q??5KC??I??)???a??G>???o?u??[~U?-??????/?c???h??18P?? ??L??H}~??un?}???? ??Z???Q^?rC?h??G??V`?-n4???$?3?/?????=$}???}??o&j r?>E_4???F5?~? {?9??1?j#o0?|?2+^?/???????*?H^?e? ??+fy?Oc?y?Gb0h??m???21(?????N????>?? +?pJ?/??(?c?O}S^1?n??^????Y???.kM????L?U?7Sg?3??ZjXmq??????V?DT?]5?? ? n?>???????)W4? n?"=}????????0?F??7????nh????????X?-?>EB??8W?S??K +?G s||>?LSt"?p3|?r?V??h'c?r????t0U??????8>P?lh?}4?????H?s?????E?a ?b??yE????????Q?|?????? ???L???~ ??????????uC|??#??th???^?]??/???4??#?lc???zaBsl?i???Bh?x?I???E?ta_Fg??f???u?? ??/????+?%?2Q}??8?B}`?|f/??e???s{??B? +(????e{?#N ???K8??(l?b3??/??|?]/??????Dim?|????b?~?:Q?&,??w??\??.??w??I?h?N???ep?I~?_???? ??F?-t+?j??^c?~?w???ZC?[{?U????????*?uJ?z?=?<]?Y???R_&?L?t,?- ?+?T???-?K??p????W??`J??q +\?? +}x????i???v???_??[W???k?????t?Gk????zq??????WL?+&D4????EYI9D?????%6??z??P??N}'?m????je????!??"?{??n??????? ????S,K???]???????E???2 ??^wPk}?0?B??ID??i??gT?7?????)??.#?j?? R?-Ja?? ?{|>tq??<1???x?G?3?a1 ??J=F +??G??k??dhbH?l?l? 9???\?9'???3{? ? ??????*~?????a??Rm?eQ???n??NB&Lkw?RF?jD?U Z???/Y?Y??2-9%?:h????????`? +??*?C??????p<ZU??+?.?? _??SN? "GU=???????,z???????r???w???d;F???N?rLl?z??????????Q??`???D?6??/?=????????????R? ?Rfl??\??????3?:F?????^????T9?-???c???????? ?????Jv?QJB\?????{? ?}?/QU?i|????? ???jh???U?K?L-??>.K??n??4 ??????iZ??>x?d ^??s??Mt?v>?f??E ??4??n(??n???B?AGx?????g?T??y????* ??f??#???X???i????????*????P???3gE?f?v4Kkd?@/>???Go?~?=?B?a???e?<`??????n?????tL??????0[????e.?\Id?dN?h?o??}}??@??7?X?3#?????~???R?k6?rCT???1U&c?8?+fx? 5? +e??:??& ?Z?aN?;s?[?A?0?n??=?2???!???? ?".?lX??8x?$`X?-??yS??????R<|)??U??Q}?QG?? +?????Cf??[ h????? 7=?)???q?d"lg?&c?U?????cO?V*??K?l??P??+Y?K+^p?g??th????S.?o@??h[? w???@??"?t?E??d @????1z??>???G?H??y?V??sL??D????ww?Z?????}w?? ?U???>h?%?? ??@?"3L?V-?+?4?l)T???K??/?y?p?2?????B?R???????5?p?5u????5?>;?{?? /?'???(?r)[?u"Z/??y??m???.?'??????T+??X0sK??=??Y???????8n?q?_???\?H??$?P???`S_eI?^?? +??,?t,Ud?U!A?-?Q|?????tH,C??H??%,2n]M?^m???/?? ????????o$?!?j})???????lW?R? )Z??%?U/e??? ???V?:&4??`??????[3?t??X?4z?w???t??"????)??k?????>??d +??8???H ?2#????V:???+????7??????:tw?'qWX|.T??;??~,?M??????x\??????`?9???fNvh?????endstream +endobj +612 0 obj << +/Type /Font +/Subtype /Type1 +/Encoding 685 0 R +/FirstChar 40 +/LastChar 121 +/Widths 686 0 R +/BaseFont /NAFVKZ+NimbusMonL-Bold +/FontDescriptor 610 0 R +>> endobj +610 0 obj << +/Ascent 624 +/CapHeight 552 +/Descent -126 +/FontName /NAFVKZ+NimbusMonL-Bold +/ItalicAngle 0 +/StemV 101 +/XHeight 439 +/FontBBox [-43 -278 681 871] +/Flags 4 +/CharSet (/parenleft/parenright/comma/hyphen/greater/underscore/a/b/c/d/e/g/h/i/l/m/n/o/p/r/s/t/w/y) +/FontFile 611 0 R +>> endobj +686 0 obj +[600 600 0 0 600 600 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 600 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 600 0 600 600 600 600 600 0 600 600 600 0 0 600 600 600 600 600 0 600 600 600 0 0 600 0 600 ] +endobj +311 0 obj << +/Length1 1612 +/Length2 15071 +/Length3 532 +/Length 15930 +/Filter /FlateDecode +>> +stream +x???ep\??%(ffV?,ff?????R?????bY????`1Y???0??????M????kb*?"????re???D*2e5FQs?)?+????????hmo???r?gTZ??9?????&??  W @ h????????Tq???????+?FCU??????-??L????w???????w?????????F5 ?jXX??J?:2?R)E ???lbPv3??6?[?\?? ?3??? ???????\??b??L.?@3?????f@?\ G???????g?? ??????o\Ak3;7???[??E???7????/?2?????????7?????t?2q?'???_7d?7?d??OI??????u5?vp?=]??e +?[?8??x???????_4?\?,???hi?lntq? ?????g????zGG;???+?r?vu?Y0!????i??7??????"?`????n???>w???D?????%abr???-?A?Sh??????'????-????&???9??????Bu??S4??;??`o@??cg?? 7??????l???Z?????q5?? Q????0???h????h?l?jf?0?????5???v???????FV???S??6?u?????v??+??"??:??????6??S???W{Wu/????G) + ????CL ? ?a?{???\?????o?? ???? +&??????%?????????????t0??3+j?&????q??9;?U?_'?o????????@3??E??MJz?k n????^_+?P?cq?zA^`?; ??o??[uS?$?G???????,??H?u?/?E.?mo???vn??`f?b??S?(??y?M(].???qU??7??vvg??G?@ +??@,?G?????0?????/ G????C?????{??Y1?T??P?_"???u5?}?iaR???.?H??| s?( (#??_?-sW????S????[?*?q?f'#D&yg??W??$]p?&B?n?m)C??a?H??!?h?\~???W????d? O?t?y4??Q?0??U???8?Py??????d?p?Ix??2l????>?7?6p?I?Sf:i?~?}???o?p-??!??x???[???T????"????2????5R[?2????X??Y~N?1q??????p!4S???7?e, +??\??w?????4? ???? ??on8??s??? f:??\J;Q{??A??/e?M?????|???~V:??-?Lf????2??????_????7??4G?<m??7f?6?????Z.???;??Zk?-??Od???y????4?;yT,?Z??sb?%mh>Uy?p?}{!???H8 jI 8E4As?9?)C??????????e? 2?_??0d?c?4?? +P ??P????p?(>?Q?H?y?#?{?3??_>??T_??%?y>f???~0??N?)???+k?S?? ?e??[??]???D?o?U;>a????ue??F??m?1+?????q#?\>5fm??? +?P???ZV@????4?? W5????gPs??s6??!?e???b? +??m????????7]-t?:?Ht8H???k S*D????c?D? ^?F??I??X?G.???V?-?Z???|2T??}*??????yQ??#??H]g ???/(?V???"? ?G)LI??????v?3?*???????L?|????Y??Oaq??5??????V7s?lM;t???-???Z???+D???2??Z??????????$F???~?L:cn??????KKG?<????"?3V???4?0??.?a]????+?T?}??%????w??????k??5) ?.?3 ??????????L2B????v?-?Uo??;}??l???pn.??x?????@T?`#/?$??C?w????Wzl?t???G???v??U??r\I?NkT??U{t@(M9????C?W?nk #f???:?m0?@?^I??u?m??E?A?????%???C???E??P???????P???+$?0 (??pM????60m????o??A;??S-????'*Ni?T???C?Sj?M?????P??XJ? ,??5c????H??-??,0?R? +X???N9??K?p??B%?pk????/?Y????????0??f???9?(??nUe??? S??"??? ????@?Q?#]F5=)? ?,AJ?K?S??????%??u?CS???%7?3?Jw???g.??/????g?l?Q??????G?m??$?????.?F?O?b??-?=??xIbDy?m#?f)???D???1???????o?f??%_??{???:$?????*?Y?QJ???l?{9w????e?????????? ?~???*?$????Xy?/8O?????????F??@??? |T\??Z?????,??$?'???M?TZQ??+0xVs?*??b???C5 +x?e????71o~D???? r???1??S?jHC!?Oe_}B???]?????8?????h?R TP?jp?????d????) +@)??F?1CV???V?*zpZ#B???~Z}:?O$???h????[y2???U;h?%???A?[J???#?&?I;??)?@?%?y4???\?j??5G}B?k??uA/-5z??T?I?Q? ?????$??4N??6???:????0??????X?%??s*??_@?HR???4???""???? ??R???????:??? #??t??2????t?J?9n???0?@????Z?" ??? ?????2X?Jer7?o????Z?Cw?Tg~]|?,?LF=??XT?????;+G????|?F ?L?N?'`+a=;?@2 + +??e? +?LO??C5|?I?????n?+?m???t??'?;w????O??GbN???]g???6x @??T??R?J?h?^-n??Q??I??+lZ;@ ???j??? Us'?F>? ?w>?[A?FO ??B???RICh?{?~??%?KB??? ?p?~??7W%??D>??j'????7??P?X???????h??????[,` L??Y?B8{?z???M???:t0i????\??S?????krv???N?eQ???b? ???40??K???xi??????[IN? )e\?w??????'t????????B?.??#HP?\?0?f????t?? +x???y??l???oy??????V?a????? ????6[e?t_G&??{????D? "?K????K>>???5?2??T?$?Z? ?????l????g'_n:]?.???~m8?o h!??W5?????????????e?R?&x7???????m?q^??S(~?"?!*w$wDUj???$?K??R?????W??8?W?;"???8????k?QD????mJ]S?`?Z??48???I??????I???????w?24}??/?u??? ???2Z????*?'?x?}p???8a'$???`yp??`?_???Rc?-J????6+f??F?a?Mn?g????4?????I?\?j???s??%"t???:??] ??,?????[q???Z]F ?l?"?o5?b??k?I?????p??F??K7????RK?x?Xp"G??9???????P?Y? evB?: +????U?l[???6????e????P/????!5?"L?"????>.KJK????+??O[?lu ??sT????RL????N??H?V-bp-. ?I?Q??????{??????K???????G;W??j?e???Nz??po???mCK%??t?T)??;??c}M??????;N??$T???_+F??0%?????~?,-2?{??F',o?o?W????q??Xv(???H? ?N?ms??{ +?M&?~"??\]?N#v?.?$?0??j##?(?3H?x??E? +??hG ??a?????"!???y ???????k?|7h4D?~?X??n??F>)????y^R???d?,???F??y??7CE??|????n?-??Y???]V??x????.???7,I?y1?M4??? ???8???W??N j gj???????????` ?u?Pr?,????Y?>????4N???fj????K& ?%=*[????N???????)???@Q??I??:????T??~?? ????'?6??H??3??=?,??n?q???6{t??F??3?m???/y?f?:?xvx5????,l9??\r?9????dE??W????0n:?dYj?*?gC?N??4?????????????5?v??5d?????`??.?????S?! ?????u]s]??x???g???M??Y'?5?n???u?{aL?????????????P??N??)i?+?I?4C?????ta??3?Ba?Q2y??T^??#K????i????f?]????~??i2?6bb??_?c????????)??}?M?4???hi|??.?1=!d?`2!'????2??G?%w?)???Y??????????4?&???????@yRCx??X?i?V??????|G?*??B?Z}Z?Eb??5z??uw ?????? ????l?@l4????Ac~t?`?y??6??Sa-?? eb????8?? ?7??pX?!??:??1???????- ???$??8r??%?*? ??\b#??q??????] +p??v? r???5?????P+??*?Q$??2??@?5?? +=g'O?? +?;???&?"l?{???/???1?u?&??g??N?? ??K]?/R??#??vj?-%????hB???L?D???FW{??#?N?gpI???o2????*VcGc????????t?f??q\~?????(? 3???n??I??P?b??)?Oo???W?h]?Z??W?u%?6???j?y]? ?bb?H. ?????v??????U????:)?jc?????o}????.?N?oq????%???S,?D)?#???y?? ??J???3!?P?%g?h??*u? icY?K9?????? "?lF??bCF?f?nq>G??T>?;L??e??R??*?e????`??s_1?3D??(??FW??x2?r???j?"?O?G??\???d?d59t?Q???????Jrl?:?ubvOc?????? +????,??W,vn?? +??:%??=S.???0q?1 ? ???)x??t???8A?&?? G??T????WCN?1??&%?wky???]H??????,K???q?#???m??-?????????m??????A?F???_??X)?w?)???0? d[_(T???T,P_,??^?Oc}?>??~??XR?o5?.?_??5??B~?D?H???4???N???@l?T????h?g??Ok=k,9????$?S?G|???;0*[????z?e???????w??_?? ??P??????n56??k??)?z?X?b?A???^???|?= +4.?PO?Xe3??!1??LN?]????]???r?|)???j4?h?HMq?~(/!&5?n??i?*?E??? ???S?@?q??X?*TH???.???j?[|??`rU?t4??L]w??zqlI?nd? ????????^???????=?U???4e??#G????l( ) ?b????Z?p^?;???b?+yoe??n>?????Y_?m>K?u?V?Ur???? +-a?? +??x?3)"?q???_$dnI`1??]??Z??t??hf??i????"???>8??3?E&????n??]/ubW??Z=}?~??T??z??????+n?? ????????&?H?&??{> +??? ??F?8}- +|?$:???fa???h?(??????Bg +jcn??S?????eVf???A?:C?A??1????\3?^K\?|?????(????????U[????Y?t\???B?Y??=? w?Ly?G?????/???T??V?:???C?\?/??_??B?]??J?:?(?????4z?:?!??o?2qV???????\p?3R{{?????V??{?b???????m?v?ww????/??w?l?U\??????-?|?&H??'w????H?d?O*S#a??????????S??7??z???8???? ????S,"y?'>??W Y4S??`Dz|??}d\???C????>???P?H????k??? n??'?"??,??d??s??c5???P0???z@7?????????CaJ)??Si?/??????fOlo????f???m?`?@w????p????????+??????n??b???~??55??-?~?[??d?Af?Ps???p?Fm,?]?L???m???.G&F??"Q>?0??[?7 ?W?M??Q?$#:q?5Q"?g??HA????? ???J_?bD? +?"`?=??;s???y??&N???,??,[,?8?}&???b\??'g??5??Z?KH??s???1:??2t???????|?T0I??M;8x??*:??@lB!f,?O??)??H?)?????????>9?Vxz???8?g??5?Z??G?DG??????????V?????i??n??+l????I????M0?-(?pg?d?\?#???Z?77?????"????,??B?]9 ?3????&?????B????????)y?-??4pdvS ??E??hc?D??W?@?[?gw{?3|?3???X?5l?^????$S???$&?!+4R???????p V5? X`bz??y????????^T??eS4??]?? ?>?YQ?.3?????{??H?U??i;?su\/?4???2?T?>??j?p??a???VI4??????n,?????bb???1If???_??&d?%?U?O?wD?d6{s w?x?k????\?Y???p?`???hsI?|>?r?l?m?<??2????????V?R?f?????awv"???8?3???q7?"??? ???*?X(???c?}vZ;?B T??/?5"?8???7?{?a&? +???????????m?m?Me???v??l?f??)S???M6?=???\Q???????r????;|?f?=?@$?????`??R?U?t?????P+?&???p???Y??G?????p??g???p???Q.H???!???}?F_ +?Y?&Z?H??????,??if\Jb+aD*????F?7??|?o.x%l?&"?&??s????_??U9???O???}i??Num?'?[?????l?/DKW?_??F??NR?0???]??d???E?W?????s4????l???i)?5N?G?????B????D???o1???js???y????@?? ??k????Gq?v7??w???PD?*??q?w?Q)?/??)?|p??x??^)&v??? p_??s^?[?,+??-??A G?t;?? ???j|???C?^?>??y?3 ??Ot?r???????m?????Q{??????p??c";^h???y?1$_'H|??????NP*????-????3?\C?<7? +M??????l??J??$???e6Q??????}????E8???A??Y??]????;35??8E%}]??]???V?^y????s??=EZL??_?}4?~?u"???k?;6Op???J?(3????H?????-[?Rt?*??!??@????????>???zm?oE?I?N?%S??Y????$?M?/?????B?x?>????X? Zr?????&9B=?%????~M??nS?dC??Wqi?a%??0??????I%??f??D&???z?N?LrEE?(a?=v?? ??}>Nw=??37=P??$` ??????x#`????%?%?x??6??q,??$?E?????|?W?S????oR@??t??[r/2??a6????T?Ac????"????2?P!?W??JXj!?i??U??Q?N}?;-???99??????~?H????]??? '???]????_??7?0q?gIVG?s?5??? ??KO%d??]^?????L?+7}??}L??????P?????7r??\d?00?m;???C0-??Zc1 +?E ?? ??b"g?L??]d????? ?????B?m???]??Yk?Tr??>???GVor?2j???D}??F +?/:??q???Go?F?G???G???LU?????%T?u????? ???v0p?!??@?????.?? wR\?z1X#?4i???-C??c-y8?????8b}U~Og???jXjtm?S??s??3 ?P????????r?1?Su??-4?:s????R'?l??x?`??:w=??.:=7??A?z? +???8?U???Yi?9???g?? ??[??/???s??SeH??????zr?_?Z?Gps?26_?CuOJe|???b?? ????Y?3?????R {&[^??f ????N????????????g3\5S?6?,?IJKl|3?~y?? +P??h?3??? ???d@*????Y??"[?? ?'????f?b??????????, h-???`NcM? +???T??O?h>??9??|2? c|q!?Q?????)???7?h???-!??"Jt???[?@I??I?CZEM?z???H[?)???wW?????D?=?(????8:?p +0??n?.??8O|???)/"+??v ??cu}?Y%_P?%????D????z?$???????'?2%???iY??}???"????y>_???t?hK?j???zH?w??????A?:??r?? ??????1??R????:????]??N???kO?=??R ?i???E??u?av}?T?"V#8??c??/?!@7P?!?H??,?4Y??Y?[???~????_???F?????????????^??4 ?? w??"?[??R??????? ?J? Z?9???zN)?ACP))?6?}P????Z?!g?k?}??g?????CE?8?[?X??J????Y?>???X????@0?q?h8k?9?@?,"????}Y???i&khI?"??????`?\?:?????g??Bn?x[?? +Kpl?????B???r>}?3??\;??~?s?.?|k???????????x9R<8m??????X??$`???V!f/??C?[??????? ??sJ?)???=??? ???s?d???I?$P?|?:????g??\?Dg???3??+c?QD;]FDX?zW-A?? ??]??)??1]L??????rdJ2?????X? ??vIC?$??K??56n???lk?e?????F?.?J?X2??.e\????..l??h??????D???B\b?p;??K?p??;?1????????????5??]K??{????????l??COK?zR*???? Q??_*T?b??=?yS??C?j?R?????r??????AC/??J?\?f??????P?H?t+?/?sQ?s??c?Tf?Q????;??*) +?+?)?^P]??m???{W?O?????L?,AV?+P?:?h?||?7?">9q?ly?D??@??v:????B????k35v?.??$????n??N?6???5??????~??????????? ???c:?|???f[???1?)?7??F????,6#??[?=?????w?9?????eq7I?E??-0????1?6??(/???@?!?h??vS??|??w????p?G_??K????Y???j??????Y???}??????l?HQ???2u.????z??^???HF?+%v?@.%Pl?o4???}K3VvJ??[?y??>?????N)|/?#?:????p[???d??yZ|???2E.M?!??2??3xO????0?Lo?nC%?iu??'???P?Gd???s???o1u$??QJuG??y???L?h`?x7????z??K??????????????? +???LNO6n???U2??&A??evu??mO?> endobj +310 0 obj << +/Ascent 625 +/CapHeight 557 +/Descent -147 +/FontName /RLZOBX+NimbusMonL-Regu +/ItalicAngle 0 +/StemV 41 +/XHeight 426 +/FontBBox [-12 -237 650 811] +/Flags 4 +/CharSet (/quotedbl/numbersign/quoteright/parenleft/parenright/asterisk/plus/comma/hyphen/period/slash/zero/one/two/three/four/five/six/seven/eight/nine/colon/semicolon/equal/D/E/F/I/M/N/P/R/S/T/U/W/Y/bracketleft/bracketright/underscore/a/b/c/d/e/f/g/h/i/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z) +/FontFile 311 0 R +>> endobj +687 0 obj +[600 600 0 0 0 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 0 600 0 0 0 0 0 0 600 600 600 0 0 600 0 0 0 600 600 0 600 0 600 600 600 600 0 600 0 600 0 600 0 600 0 600 0 600 600 600 600 600 600 600 600 600 0 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 ] +endobj +290 0 obj << +/Length1 1623 +/Length2 9318 +/Length3 532 +/Length 10177 +/Filter /FlateDecode +>> +stream +x??veT???-N???pw?@p A?[? +??? ?4?K????!??Cpw?`???n???W?????1????\k.?k?????4?%- f at 9????%???????A?*?R??;3;??G????Ma X??-2 at s?[XX? qp????a?gfVV???1???y?tY? ?.@;??= {??;j??5` ?????)????U??@0jjPs~.??2????K`?????)????K? ` +pr???????@????99=?@N+?)????9[?I?y??WBP????3?L?q?9?CA0?sT5?? ?6????z??gK ????????i?Q?)??]ab? ';S????dP?_i8;??V??? Z?B-??NN?4?????:??zS;???!Y?G ???????9?9?9????gX??7???-?????5????0?'aj??,??????sH??Le??????-?[?????w???!?????S?9??????r?????\3?????3?????????????t??????1E??s3$?V???ssq??c?$rZ??`??KS??^????B?@`?????.,?7??s?????? ?-????J??????VG????X??T{?{7 ????b???5?e?31\g?????sR?????????????~??T??zBw??s?V???q????t?????(? ??-? ???y ~d(????(_???{??i&?'T?9?{????F?V?3[V???7??g???x???'?7o? ++?u!?????.>G?' [f???4?4??n?v????b?$???Q????? ?6?V????o?U???C ?z?zczW??Qnw?zO??^??)????Uc???}L!??.u +??_&q?0M@??0q2`??9?q +"?s?\`???F??qk???}/??Z??IzOkH?#D??? ?G???o???O?S??????A?????iO?=?? ?+?D?z??????????pkJZ???? ????1?t????=?}??H????y9?!??Pb;b???X??????]?F??Vw??; :'?+q?3S???h???????????k???w?APu4?k?l#??? ?m]}????v??h?|Ly?????>1?Vg?x?mK?hs??Q???C&?n??B?z???r?????? ??v???5s????kw?;#?C??? ?Xw2?3?(R;?c$?c??e^R??5?|0?? ?&??I????3?2?? +.????FA????j?gM?pW?v????? Hf??;a7y??o???O??O?+G?>`?&"??h???N ?X??\ ??7mj??W&?9?;????bI?)?IZ?]??,0??]i#f?'?s?X?????q?u????zWx???D??N???e????~ ?oK??TA?*?$ 38J?????}? ??dK???t?%?*/v?i???\?r?}???n?????????zX???????1A??3?7?????&S}?W)^????S9?????x +? ???8?x??FS??8?"???w????)????$i?~?H8??)L3&s ,K(?9??z?#?Fj???????????v?p?Pm???!?????X&" +?&??bG2?????$c?],=C?????eU??:,u???C*?|????'??????u?J????M?y?]??q?QHl???L?z?7/?&}}?h;???>@??.~?.-ygD??B4I? ???????w)C??W>}+????5YL????:/ ?*??h?gl???Q2? ???`?Bt2w?f?eHJ?v???i0??????q?T?????s#??zui9(?U???2S%?K?tEQI?T???K; +;R7??$^??$????? SI??Z??;3M???d?????$nu??e????01~w??o?R???c???^?m??a?c??^C(?>GExxo????)u*?\???H??/F?V?sS=lxT?@?0`m??n?????D P?ch?`??Yy??_????????M??^'??????)?Vw??????1? 3X???~!2B?`?KB???({Z(????? ?U?[????GW??? ??>U[B?????&+v???;?`??A_a~?L??1"?W????0?r?*??tv????Q?????????? +W??????)kNU.?c?rF{?Z?????LU ??-?S?????< R???5???H?????w???-?????????@@??cQ?6Y?D????5?3#..^? +F1^??[???`4 ???????{m"?F???:7??9i???J?S??O?Rc}?8?(}???"??%5????T??bJ???&j?1??1?Z y???? +??!??Z?]W??A???1??B?#??B]??G??V?v{s???;??+????#????w$?vtB^????"?J??W?G??#7?q??M~0?????D?>/?B?VK7????V_??2MY?93*?s$1?Q?????[rA?E?????l?W?/??ywj?y(I?3?(j?????xro2-t????tX??????3.?C???6?_9?????2h+?u0?;N?M?? ??^??D?5??????""h7?.??!?f%?6M??Ek;?1zA?o??,??????}??l????%?9S?>?Q?) _$J4?*??j???O???x??[???????p?\????d9?? ?:M9?e???$???+??QR:???j$ R???J?6??#s????f????d??b?w'/?=?@ +?>9C??g+~?VJUi??c,p??????x???iT???|??.????&??K-?????;E????c?o?e?)P?e???q ,X"??h?????K?T??\? +??vZ???-8????J@??+?`*?d??????{????+s?pz???????>????U???R?Y?????????c??C? >yK??M?? ??J??NK6??"?&?ju????;Y??F ???l?O5A? ??5??j??xu?e4??+??'?58d???d???n??????7.?????????od)Gg?PH???[?T$? ???Y?!*$????< ))??}?;??????;?2?1?_???Z?j#qA??#?y2?Z??}?*?a??G????Q6??&?P?N??1???????~{0?v??R??X ?#Sa?? +'I????u?ZV?%5???|[\[???u???N?Q???T?D?7ppu? n{?q ?P????H??;R?A?,????d?p2?H?(S!???N????1l?]???>M?WY#y??6+$?7?S#9?$??n??S?K> 2??%??~l?????E&"???????6??\??08????b??m??6??;G%????n??? ~???hS??'???z??LYTF$e ??d?'Kqf?? DM+Z??TI??^?? +O?C?L???k??Qc??+?????$????i??????I?v"%?????g???I ?V??!u3??|G? 5l?(?.e4??G????9F????~???? ?`*?k?????2B???E?u?OG9%?Z?7???X ??E-G????????i??Tc??fv??u?????Ka?5?Ur}e8???]gd"??"?*???J?!?&9????J ???y`? +??m????~4?? ???tO4;I?lS,2U8?tr?O???????? +D?q???^| ???u1??????M?????C?S6??B?Q??????/??h?R?>;?????????????h??!? ????= v?*?>?????T?p??x??9?AnPy???????d ?~G??:???y??? j7t!?????yU`???F$?C?????5?xj=?5L{?q??3u;??$????^?l??E`*?+? ???5??tg?h{?4^??+??@&?????Ge?Vo%?_??q'???a+?6??A???UoZc??QA^2]4???@c??? ?s?%F?2){ B?????=Z???p??????????rc'W???r<9M??"i/aV?T?R??L?????|?!???=(?#)????m???8:?gU???c???'*?*?Fk??? ????s?U??????????9?E4?7?oX&?{R?pn?C,?????:?g?? _? ???c2?)O,/ac?oEg?@??<2?c?r9?v9 $S|?@7????fR????_?c????$???????^2?????? F?Ys??>?m???l?Z?????k???F??# ,?????4?b! Nh??????v!a?c`!????%?????ehC????@7???aOJ??9+*??????p?P???i???O%?????????????K????T?? ?\*9??8??uC?^t@???VL*?S??/?????C???uwj???&%D?CN???? ?q????U???IQ??:6.??T???#?????c? m????,??I'9E%???kV? ??6???nX??A/?k] +??E??_.6?3qDb????PZI??n#%y%?"?v?qZ9Za?-)}??????z???w"9J????#???&?=Z?!uNfT??#?? +?xt???BL=?#\???^?{???~??U???v?Q??'I/z>??j?+?????,k5??D6??????;???X???Q??Q??6?5^b??l???b?'Z?P"?*x[!?'???W???4{/ ??yETP?????e??h?m?" #\M?1?NM\_I??M?Y?OxG????>? s~??@?yQ?w?phC??1?'??,<;???;?HJQ??S?????y???.?"X?4?c*A?=?#c|????K???-~J????????\P?0??4?39F???UrQ??-??f???]{MI? ?tPZ??@?I??/??O?'8=????"?Y?g?c+???N ??????_k?H?p?6??z? +??,?M????Sx?p bw??q???G}?V)i?g??=?h_&x?Fm?b0A/?/$???!A?g?[?????B{J1??!V??0??+?B2&*?b3???Vmh???C?,????K?[wVM???x???g? +???K?k????2 ?????J|?~ P??j&=???hw????>iN??S/???c2??[??K???Q?k?~}????+????? ?e=o?;?-?\1??'?????!?&???r??wG??oK?????H?Y???:????!c?k?R??? ??????q41??91]5 ~u:t?Z???????.c3"??????$???;+ ???|Q?q?????r???zI???????u%?W?J???]???:?-Tw??1?]??%?^??h??`??i?m?/?CL??q?L?? ??A?3???M???B?????H?W?????Z?EE??7Q[???F?"?d*a?s?g6?fl?G2|??????? '????P|?????hd??5iu?????E^?t??X?l????o"??I??t? =?.?o????}??K?JV???tZ???1b??% +?????D????,rd<20s2?L??RH????[*??AY?5eS?}??????????1????????S??(O???6fZ??1????F:?vqJ????e?m?|K??]D?V???q??r?/?a??u?{?z???????*L!Mx??????Sff?q?b"lV??p??m `?Hh??+`????=?D???D??/e????9e?I ?M?????u\Mw???N??%?9?B>p?????[???_????0?.G?v???!1+_??? ???(B?????p?L??|?\r)?au?V????&??? ???=??\Q???Fk]??~??{??*G??!V4?:?H?ZHOO x??B???u?M$??? ? +?1uX?}?V@?M??W????~??:??k?rw0?.?Q?l?h}k ???? wX79'???vW??]?E??p???\?c??? +?b??N?A???h??6?o??%D?b??X%?-?oK??nY6?rJ-??_%??I?????z?*?>:?????#?? ??:?:wqE6??????CK'?[?wpk:?/?[??Q? +Y?d `?}l?V.????I?C[??w%A6F~??7??5?n`)8 at P??5J????c?5 ???lH?+?????9?.y???/?>Z'f?#?+??}X"vrP.??]~?"n"Oi??I?WD??????(kq?J?}}$?.A?bd????8Z???FIq??4?.?p???&_?? )???:K?H6[@???qd????B?|5<>5?w?)o?cyMd??B_?@?^F??????y??'?*?Z?????j?N|???CK???? ??N??4)n????P?=??)?l?a?G?QQ??????7?????m????B?.e*L?F?????.???G??{\??K?r??/C5?#8???_v ^?;?,?+?????????R???,T?U(V=Yyp[??? ????????-K??h_??&1?}?=t?8?x1???????1?;& +BN????????Q??e????U??\?[????????%??????X?o????C??6??Z?5I?F8???C???}%???L? ??vEo? ?d`?Rk??db??1P??_?6??6H +???ZTJ?c?{[)r?/?????? s;?)?7????????endstream +endobj +291 0 obj << +/Type /Font +/Subtype /Type1 +/Encoding 685 0 R +/FirstChar 2 +/LastChar 121 +/Widths 688 0 R +/BaseFont /LRQMWS+URWGothicL-BookObli +/FontDescriptor 289 0 R +>> endobj +289 0 obj << +/Ascent 752 +/CapHeight 752 +/Descent -206 +/FontName /LRQMWS+URWGothicL-BookObli +/ItalicAngle -10.5 +/StemV 78 +/XHeight 547 +/FontBBox [-115 -232 1275 972] +/Flags 4 +/CharSet (/fi/quoteright/parenleft/parenright/plus/comma/hyphen/period/slash/two/colon/question/A/B/C/D/E/G/H/I/J/L/M/N/O/P/R/S/T/U/V/W/underscore/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y) +/FontFile 290 0 R +>> endobj +688 0 obj +[487 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 351 369 369 0 606 277 332 277 437 0 0 554 0 0 0 0 0 0 0 277 0 0 0 0 591 0 740 574 813 744 536 0 872 683 226 482 0 462 919 740 869 592 0 607 498 426 655 702 960 0 0 0 0 0 0 0 500 0 683 682 647 685 650 314 673 610 200 203 502 200 938 610 655 682 682 301 388 339 608 554 831 480 536 ] +endobj +258 0 obj << +/Length1 750 +/Length2 576 +/Length3 532 +/Length 1110 +/Filter /FlateDecode +>> +stream +x?SU ?uL?OJu??+?5?3?Rp? ?44P0?3?RUu.JM,???sI,I?R0??4Tp,MW04U00?22?25?RUp?/?,?L?(Q?p?)2Wp?M-?LN?S?M,?H??????????ZR???????Q??Z?ZT????eh????\????????r?g^Z??9D8??&U?ZT t????? +@'????T*???q????J???B7??4'?/1d<8?0?s3s*?*?s JKR?|?SR??????B????Y??.?Y???????????kh?g`l +??,v??HM ?,I?PHK?)N?????;|`????y:?ykC?,???WRY??`?P ?"??P*??P?6?300*B+?2???????t#S3?????J.` +?L? 2?RR+R+?.????/jQM?BZ~(Z??I? ??% q.L?89?WT?Y*?Z? 644S077?EQ?\ZT??WN+?????2?A??Z???u?Z~?uK??mm+?\_X????????7?D?????Rl:/P1?d????????(??l=U?h?d?_O??E?k?v-X1??t???`????i????_y. ?1?????????:?un~Q???3/??S??}??]?? +???$e~s?]F1????/??Q???m????|<?????/??q'}I???+6???E??g???xT.??G??gt???v??G??U|?????~??]?R????_k?9???:?{?p??G?? ??d}dN<6??-uB?o?H??=c?M?vH??z?q?a???RK?~,K???}????????m??????yo??~?????v? +?_????s>???.#????????{?/?????k????\m?|??r???X???????ad?j|?????R/?,2?p?0, H?IM,*??M,????rjendstream +endobj +259 0 obj << +/Type /Font +/Subtype /Type1 +/Encoding 689 0 R +/FirstChar 15 +/LastChar 15 +/Widths 690 0 R +/BaseFont /MFICNK+CMSY10 +/FontDescriptor 257 0 R +>> endobj +257 0 obj << +/Ascent 750 +/CapHeight 683 +/Descent -194 +/FontName /MFICNK+CMSY10 +/ItalicAngle -14.035 +/StemV 85 +/XHeight 431 +/FontBBox [-29 -960 1116 775] +/Flags 4 +/CharSet (/bullet) +/FontFile 258 0 R +>> endobj +690 0 obj +[500 ] +endobj +689 0 obj << +/Type /Encoding +/Differences [ 0 /.notdef 15/bullet 16/.notdef] +>> endobj +191 0 obj << +/Length1 1605 +/Length2 13195 +/Length3 532 +/Length 14041 +/Filter /FlateDecode +>> +stream +x??zeP???. ????????????????? 6??????r????g??????n???????'?????;?????2????P???????????.a?lna,K/lgg?4?????8 ?-?lE ???u? @h `a0sqq??D??=-???T????t???0??w??J' 3[???hmgo?u????^? ???S k @D??????JB^ ?:Z??Y[d-???N at j???#????????_?91|b 9 N?@c??e at wc??_.:?=??????s ?p?9?:???`akl?b??O???????>#l>}?`??????-???Y??????????_??,>?;??H;c??J??? ??u6??u8????e?X8?[z|???w????????????f??&?@'?O?O?????:??zC{{k??W???,????? ??,?9???s?Y??2??Q?lM??L??????????w????3??$ M?l?=&@SXFy;?????;???D?_??E??y?g???F???O???B??X[???^?? ??u???PC k????q?????0?? ?? dk?)???N??@?o???SC???mW?5:Z[??????z.?q?|R?????l????&???S??Y3J??I+J???U?w??O??U???r?8:~???Q?,????p ?h ??`g?l????\??30&???? 6????V? ?????/5l??????;C??{???????4??P?5eg2?<????;e????v/?Q?!?D=??bNv\??ImokLQI???`?????????5??????8?w Frj???????{???????+??]:?e????+H61?7BVB??T?0?t??C?Z?15?Y#??KR?J?G???{:?V?KK??Bk???w?9??????????g??]???;?????ah?.?U_/aH??I?h0?{p???0??nP\#}??v?1?? M-????P????_???U????>Ek??s?h,?%?47j}ii??1^)O?J]e%^?oR;r"??? 1q???lY_` ?>?Y??Nn???-??????;r?:??????s!???Y?Nj?d???V?5??ri(q1?(?y??w??2$??? r?????????/?"?ATu&d??@"???x?7n30?A??#???+?UI???9?,?WQd??*?s????Z????B +?Gy?v??}?????TG}?[?????]$N?v6???A??@h?"R?_1 ? +s????2j?????????zi?[??er???n?YU?R ??(?????????%??????:rw~?-??c6;?????m ?????BU???3???????' +%??s?????????<?1?1?F?J| +cw??!?V??GnZ?~ ?o??w\h?*??Tn?@?*(??b?RvW??bpAF:??`????????~?Xi???#O?;2??/P?X??9v??R???i?5???-?E+??nB-?KS*;?Ii31{?@? ?? ?? {G?? +|?\CH???p???????i?x(@?/???? ?}?_????????Ur??oQ?<90????????????`??????8+???5NI??V??8l???$??=? ?X ?B?}?????p???? %?d?)???{VxX?????)-Q?? K&J??A+L?r=?*r??u?????`]?8?? ?#?;o?????????F?? +E?P?k?4|??????IW???w#????Fc?????6h?  +q*??'`??*Lz?z?K???)??+.:?????o??vo?lP??s????8o??RUO("\XK???`B'0?k?V???,??c????5Od))? .?Q ?5??U??????Z,lY?F? ??9 +???u??????H ?????T??5?G????]s/?T=???????z??? >?u<^? ?u-&?e????_3Q?-??_oG?@,????*??jy?dCK??J????$m????`??~C(f?K?d?%w??3X???6???"???j?R|?????>?e??6h?x +e?=B???b#???6??K$??? @ifbO??#?1H???O>?!??K$D?0??+??2??5d?h? +blT:?J?????TE??j"???????/??a???Av???????0?????W +T{)8.M!?$????&??b(38?1??T???\O?? 5q??"??nV?@9??d%;??v?????j?????\b???????_?Dr??1??:c?`ESz5???k??%??3?C?\|?c??XJ? ?W??%1?.R??b.?9??m??W?G???_nhK%|D??=????#??A?????|?M?Ml?f?]j??^9??(?x?,?"@?z?????K_P?? ??G???8g? ???66?9?.y????R????7"t?? ?#T??????.?]??Ov?(Ls4?g??K??????C?X??T??????0??b?)?|(?1{we??????@3? ????5?????a????xB???^?M%?I`? ??6]??????R?&??!D?????????0??[I??zPY m???_)????G????,?Tp[\?^?#???(?"'K?_<?x??m6??????J??A? P????o?6%E???q??=?>wu`???A}?????q ?3#0?????gp]??????SB?s?????F#9'????Hi?DD4????OP??W]????f?????6X???q???6??l????>???????15{???D4??k???????r?9????S???aN??&K?+??s??? +=??au,?E[%pT??`? ?o[?o\?x?R?V>bo?????J?"i^?V +_?oi?;;f???|??o9?d?8$?@?^?K B?t? ??f-C#PJ{?????@???7#? ???????&??" K?Z?I]?0??XA?L???2ML(?c>??t%?;l?,?? ?????o?!???:?1?????????G]E???sTA?????`n? uj? ?ygH?A??dKQkJN? ?9?Eu??-`]??^ 7N?{GW?_?A??eR?A?U$??????:z'"? ?{Y?A???>j???'?>???#????????l?*???=?ji8?9??l[?>????{??B??????`????LX??'s8'??? W???6???????????8 ??`??{?[?? ??k?Lo??? ?Ic?V;????????????A????-???H??j????IV?C??y?2z????9~T??H?6?????9??X?[W?*???????O??n??r????V\?5?6??*.?????2X?A????N?_??:?E%????}C#+ ~?6K4??)`??w????Y?3??;Q??j?nUh????????????%?\miF????gt?P?7??????????k??{?;(]X??d?z??r/I?????&?U3???|???,?{???{q?7???+&?rJ????3?D ?D"o??dDjdI???N???????? ?#6 ???#??X?>??????????sx7?hKv?L???5-}??????!????????u?B???T?F ?}wq K??#???d?????????63?a?l???{?Uq}?n???sD?%-#???V?????????Cu?J??,???H?c^?X?a???m&|??P????w?'0??g9??? ?u??????????Y??Y?P c?^??l?v?-??Z7???.????"B7e???zN??,?[?N?I??????_)???i0??v??'?????????6??=?P????p? ?????E?w? ^#??ah$????dU???a??]?n??? ?)?!x?1~??/sQ.$?V??p????N?^V&??mv?_??N?#@?hV?Z?;??}?m??^?`\?E?lN?? +? ?@8???*S> 'L?????? Vf???????4s)?B.lN???^???????\4?!:x??L?7??(????Q +????/S?A)G??~?j?q??KE??N??RyO???%$|N??[zh??x???%=??????wFk?wb???.????? "+ACN?b?=???$????30Z??? ?s?H?+?` VG???Q?7???????;??\D?1?)E??X?v?{x??m???b?????@N? Pn???l?!????? ???Kd?q???????7R???????q]0$????????8t'n??????7?}+N??U?????qlr^./G(&D??OK{?s?,??*?7D5??E?# qgDwUy?bEk7y$Z|?(????x.V?????6??X"??a>~??? +?w???w???:??c;?:?????S??e?Qd????31?+?C;????\u?).X ?,wC?f?tWu2??h????FWp?Q?f5???cqu?/W36? Q?q?8?? ??9D??ym?oNc?1[??w?-?)???lh??UP?u???Km?W??O`??x???T7U)?]?F +??????B5????bAf????[zb?um3??Nz?i:??XH?M?????jc??XL?N?T??M(CuY?7]?J??????)b{????*/???@%tZg ??n*?T?B?3?m??????z?&??X??? +??M%?9y?B???w???????rHmk?tZ=??2 e??9F?!3B]?O0??? 7????4ZB?Z?????????????(??4)w????&??????? +g},*q?*????j???E?>N?4g)?:?????SC?????????/L?{?tL?? ? ??HA?????L?a???|??iCY&:??? +???????^????s&??s 5???a?~?3???BF??????^?m????QW????^???/?tW???;X?u???u?i??? ????? +?;!g??D?????e????$WO ;N*?????T3p?p???Q?)y???x??????,? +??*?m>?????ct]???!x?????K1~H?&???^??"?3?????P?O?9?+<??c?Ji?{??B??0???{ 0??U[?m???o?r?2?s????U})|? B)C??????d?????6=?&b???&?"?Lm"S;?)?5???'?p??]3?ousd????g??wX????Aw?????-,?S???b?f???A?{???^????? +?R?N?pE??x#?SPJ?]?Il???=?F??m?T???Q??;&????iQMZ)?`?8?1??#?R~"v?F???X?1B%" +??l?t?y3?????98??vS`tp?o8n ??????N??v????a?Mob1o???m?5y???e?~??:????H?PQn?q?W??M?T?}<'???2"v????????XK?T6Y?y?? ??>f??k4 +??????V#e`?0?J????W??Q^?DKHs??)?>N-5????????r???E???Qd??b???N???d?8gyOK??????4?81?2 U at M??e?.??HK?????!??evj???6?a?'?KDK1??A6Ix????hw0?7??????='??tZq?k?4????x[?g?~?,$?^? ?4???????yl,c?????????B????{?O?TZ?q????F??t????}?80??y?O???C?4C???.???u??, at zu?\aPLk??`F??2g+??????? R???]j:?J???CI?5.?7???qs???c_? +r%$??$???_?1?v? U o{?bb???}????,*??o?l>?Y?????N??j??BO?T ??]???l'?{??q{?1??H?#f?*?|?fB??t????(W?F?Q/\???]x??:??????????%?f^??,???8 ??K??@j?)k???=k0?????_R??T??u???q???"Iu?P? ?-????1T>1????;??>???zn?zj?\F? X?? ?@? ???t?r?nX?:z???`?Z??CUWx??'??8?*?SB?U? ?({?P???)?? ???<? +C?? E????I????cF??????????%???^I?C???"????GWYL?q1???7????,?@??s(FTjiN???XT????}? k?????~??SE=td?Y"?f?O??w?k?76+?]{.???4?y??/?5?;??????y??????^+ ???4P???Ae?LO??D1?ul?w*#????x]?N$qX?n??? ??h?>?9??H?????X??-???M??C??????NoB]?????L??G??y??H+7?&????_a????MHP???????? ???)???;???_?dD???E????"(?:??v8?????e??????5G??g? ?G???'?T4n????v?LT?Zi???Un/? +??????=?%Q?s?x???????D???k7?7?? )(@L?n???DE?:?`?E?9:?}13?cL??LH??'??I??(?`?3v?^9KC??@????C??k5???'???z*?E???zP?N?bhLa????wU?8???%_??9?q?]??"/c??V???6?g'u??X??Nu ????A????"?k?:?4[????????? ?2??@s???u?Vm?2??????=?????/d?-F?????A!j2O+??v???n> endobj +190 0 obj << +/Ascent 752 +/CapHeight 752 +/Descent -206 +/FontName /IUEJQG+URWGothicL-Book +/ItalicAngle 0 +/StemV 74 +/XHeight 547 +/FontBBox [-115 -240 1151 976] +/Flags 4 +/CharSet (/fi/fl/exclam/numbersign/percent/ampersand/quoteright/parenleft/parenright/plus/comma/hyphen/period/slash/zero/one/two/three/four/five/six/seven/eight/nine/colon/semicolon/equal/question/A/B/C/D/E/F/G/H/I/J/K/L/M/N/O/P/Q/R/S/T/U/V/W/X/Y/Z/bracketleft/bracketright/underscore/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z/quotedblleft/quotedblright/endash/adieresis/eacute/iacute/udieresis) +/FontFile 191 0 R +>> endobj +691 0 obj +[487 485 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 295 0 554 0 775 757 351 369 369 0 606 277 332 277 437 554 554 554 554 554 554 554 554 554 554 277 277 0 606 0 591 0 740 574 813 744 536 485 872 683 226 482 591 462 919 740 869 592 871 607 498 426 655 702 960 609 592 480 351 0 351 0 500 0 683 682 647 685 650 314 673 610 200 203 502 200 938 610 655 682 682 301 388 339 608 554 831 480 536 425 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 502 484 0 500 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 683 0 0 0 0 650 0 0 0 200 0 0 0 0 0 0 0 0 0 0 0 0 0 0 608 ] +endobj +179 0 obj << +/Length1 1606 +/Length2 11602 +/Length3 532 +/Length 12452 +/Filter /FlateDecode +>> +stream +x??weP?]?- ?;?qwwww'X?4?4 ???.A??wwI?w????73??7?????u?????r?^{?sNu?Rjh?JZ;[???PVN6!?????3?d??*t^??(????? ?????@k? ? +???D?H;?xA@?vP?+#33??=?,??=??? d ??~x?]??`?+???Bm ?l@?@???????-3ZC?;8.c???~0???^?? ?????-|S????k[???s??????????7G???i>?5cO?w?v~??@v?R??#?h??y? #>???qM-??GD??vn??-c?GA?? ?G???X??????#????????????7=???9?oi?=???\sH???4?W??Q?d?`o>?M?:??#t6VN?~M???m"? ??c??7?6{??a?? ??S?sY???????x?n*?#@?k?xE?a????PEVv~ +5????>?S?Tw?b???C?(???l???rI??G?????e???????/c?f???z????g]M?9 ??????-xd??7TZ??????????????h ??? ??T',???????????Xc6??????~??HA|???:??BU??5a???5?:??t????a?3A???????]?zK9(?[? +"?Zcp????Q???D,?~ QR?s\????e:?X????kn????p_?p{?)? ??L??[????^0?V??????????)V]?\nm?V??????&.n?j?????0?"????9???? pK??9k?? &B??\yK ???lrw8.0H?? ???e??w?:?~????\???k??qV??L?:t?,C???`l???^?<???,??D?????-aN?U?Y#K? ? ???Q'?~?p??-?K?7^.??@??i????7l?l??o?? HM?.?G?3?K~?0VL*???e"?}??:w^(????KZk??t'?~??????u?He????p?^????}M??"??]?W3]G?#y/??H"E??j?y?|C'?>?C_A????|???/??=? ?B.??1RY?2?2?? i??d`\??+?3????M4?o&H'T~.L?se?;^?l?Yw???????_??\??;?y#&??2?~??2?J?pi???V?@;?p2)|X7|??????*tr?n`Xz?4~???d4q?r????yB?/????6??O?(*G?FB/??p?~%?$ J???.$S?'????v??? ???????b?m??P?????|??? +???????`??0??i??Er?9? A&mE?o?Rj?3i?~&?^@>??#I^q0??p?????H?YYjqn?\51 t;?Q?Ji????^??8vv?4#????c???????1?p??? ???Y?V???/???g??05??gU?s????[rKJ??????oM?~????r??jZ?Cc?Pz?h???????a???c??|QxY?R d???@5mw?]??@???'??c?| ??A???t?}?????I?'O?B}2?=3???I$'?i?R3??$t?????l ?????Y?D???????r?W?}??k;???????[/Q?????\?id??3>[t6te?N?{?}??@?ck?ZK??:??????"??:??n?[H H??P?f?????f??DB+???I???*\?Q???B ?o????? ,mm^??? +z???Uo??Wa{???Gx??d?#?I+?7Zx?????J?%)????'.??c?m?f[?4B??E@???????e-??_?BGe?:?z|'1?Zv3;????????]u?u?Pn????l5?n ?????? qS???-o??+-??????1?K?L?Ra??w????????N0|?????${?q???????.TR:?????D?c?u??????J?????d???%??3??t=?1??r??u?????k??Q??Kw????P????4?V???Q ~F?_????,?y?3?C?O??(#??N?X????????+`??,6?/?G?k???1?=?}??????sgk}??G yGR??????? cf?CL ???????D???o???(?;'?D?LJ:Q?u??????V? ,?????????K??\?7#?C??\t?????????=~*???|?????E?d?E?'v? +??iD ?e?F??????.r???4??+?8?k!?0???sPN?,fF? ?{B??VXll?f)*yg????!????L?9????? ?T?O?6?hz{??? ?5?T??p+??b ????Q*b?@??????R2 :???f`?1q?L?????[?I` ??k<[`?7d<^6?B????Z?)p?t???( +i??<Y????7???????w?} ???O(?? rq>?i??Z?m?????[??&???#?5? Lg???+??> +??????=|?? &????Y?????D??`?????'?????2?>JW]??@?+??a]?y?QG? lz?? IS?)$n?? ???6lV#?;>??????a{?Y ???+?7zm?`JF???,????9???????.@???????????` ?L?k????ga??????w?????g1?|??>??v?:c-? WQ?@??YR$??~????K2?y?Ug?~d:?.?M??? ?H\???G??A?s???????$????L?c?%H+g?p3mY???,?M?A?????0 z +?g???{h1f????? +x9,?#R??c?^??E?|??I??Q?M +gV$% ?f{?I?V?X??}?M?`??@?? ?mM7????u????+?~B?3???\y?LR???B?zh(B)e?%~+????"??&S????W??6???Uy? ??m?????:???&??%??0e?]?z??l?y????@???g^1*4b???I??[?????4?'??`?'B +???D?Y?:? +9?:HC??*?-%Q????OC???Q??S?,???W??`(?a?o<+????.????Kp?????}+?O? +?GSut?n@?c?>?;???a? +??c?4~?)?A???^ ?)?? '??????_?/????4Fzk?tO?X?h??r??"?C(??????O???I ?,F???~K0??D??bj?? `z???zzpc?????B???Hsj?L?3?z?m?+sOX?{????X????;j????Q??v????M??f?\???{????%(!Z?`UxQ??L?/ ?=????Vn???? ??????Y?P'??;:?L$?5D??GQT??]y=?9Z??I?/?????h??eb?????S?l?a???q??`?0?jawpK???K????^ ? ??????_'????o??DY???? {S^C: z?P?<0?_???F9.???d??2??h???d#I?? *}V9?s?(6~F?zc?? ?0a??????l)WE2?????{?R^w???(???m??k????Z????J???WY kT????7z??h??"c!? 7???$Z??!??????n ??'JV??1??E]??}?6C????????5\>?;?V???'4?Q???I??4??????M\?V??????0??t??????X?L??@??.k'????H??D???????ud?kT??O???H???C?? +?,??????o??????????0??]gt0?U#u^? IO??8????l??? ?(>?}?j%xG2+?.?OEf?^??????`e`??S?M???n????????}?)9?8?^???1????H????????????0tQ???2j?&$????U?E??J?????T? H?N??PV?/h?????K[????XW???}W? ??utRUc?????? +?.>??zDZ%??3??G????K\?}??xn?x?!?+j.?mL9??M??m???#??k ? ??A???!$?E at 8N??.?????7?!!??8??????;b????/???G???gU?Q????R!? Y?1?t???K??#??v? ??G???????X??7M?f??)??7??3???????d???.??y?(? ?s'?%???w??????|e?????x???ZA??f$>?? ?????G?$? +H_?n?~H#?????C?????gy?Y???v??pi??&?AC?a??z???Mpt??i?y???SZx?M? f 0??g??& ?d?|?2??_\X???',?|?X +?0????;?????[??]???vbL??? ???Z???yb?_l4???(??D?jJ???T?Q???l?> Z??????sa?!?,???O????M?????^??5??T\??Y?o6????~H??? ?G5??a?*?|???V<?????1S?g??R<n??6????2>?[?Mw?Z?/,?X?o?T??u????l? ???F???weB2????o????w??@????6????:m~i??????????!J?g[??I?=KT???]A?/?d?{????&w=????S???????????RE6? O??ba???f?Cu???RM?-s?1U?G?*.?Z-d?GS[?O???????????5(%??#U??y-??D??#(A$??8??????Y?????u?/z?????Dk??ni??~WH?C!? oR??l)Hy?e?]? ?9??}.L?'??d????(??-??e??8?6???a)J????????j?d???2?X|?d? +>>?7?{?-S??$???????u?KO? 9+? ??=???O???(???n?[ ??&??a??? 9J/?bA *iB?C???&??:v?p????vk??`f?M!dN?{Mw?~?6aH??R???o??A?k??bs??0??6?T?.C?????y4??Rw?RO??P"x7?????Z??eY???v{fH????(mCGw?????L???????`?D??;?Jr????-@>?Mf?Y??E7? +C?< +?n???Z???T? '?????9?????4?l9=DP??"?d?h7?}?iw???]?B? +??kX?$?y????=??G0??#uQ,?V$????ujS???B???J? ?I)?????W????h??I??ZV ?bT1???6???CcY? +u????? 4$??#????J?3?>a?NN?4????c?????"??S^???LKY????X?xl?`c?A? 09??gv???Uj?)+>?VS?e?????J=???????M??1C?M?Z}??x?G????+?XE????????v(??p?[???c? F???_??t??n#??U??.R?z>????hqb??? ????@?U???Z?@a[??9??8yT?3??H??????VW!?t +???p???X;???9k?/lK$ ??/?:?8?s;Oho#?b?u?NZ?G???c2?V?ry??????+?~x????=?D????4?F??;?????xU?????d}?q? C?&?=?z?????? VHUL-??????U?g?^?Ji!C*?Z{/R???9?-?+R?QE ?? J?T???,?J?Q\?~??q????}3?o?V?????????q?????-???????`Z?? ?y?7??????t2?+"D??I???????????V6l?NT???0RUR8?A?~Y?&'o?_)(O??M?\??J?=~l.h??\_*.???9 at W???}?m?.Mq?????]????#??T?%???V{????? ?7X at K?????lukk???!???t????????clt???K?1?b?ba??0??v?y?'?_?>_???&+??g?v*???s?:pZ??m@??u?{aH? ???N??@??q!?z N????M@?????;l"?e????k????{??/?x?i|?????s!X4*?}?(????S Y????"??NLa?|????B!???B9>?H$??R5$???s????o???Fd3~??FlBy????;?0?`ItQ?=?=5?$0???????)? ??$Ptv??j?h?9o?????z>???/=|~?H?HnE?=??\??C3r??:??E?##? eq???x?? #??}????:??xstS??????R??G? ????'????u?^!]???????????mg??????Q?"{??Z??|?sRE&eQ???(c??c)v? Q?=????y?[?l?????/?k#&u?v?|K"?4?s?mr???|????f?q w?%??????]?$????????gH?Ia??i????1u??,`??K??2?UW??v? +??????6?@?????^?A?|?(???\?CH[???>??d6????Z]???S0xd???q!??L?}E?w?8G???N?&?????????CQes???? /PC??c??V???4?}??[HE????/?Y?????$????dSI1?????nD??B??????Z?3??=???KA??CT??????E?????lt???????????`?~?U?+???>;d7???mD??0`????10?(?e?'??;?Yj"????{??t? ?????&SP??? ?*/?'I????<??()E??????9???V?????&A#?????+Sx?w?dv??vg???d?XB????E*???????`???@??, (?W? endstream +endobj +180 0 obj << +/Type /Font +/Subtype /Type1 +/Encoding 685 0 R +/FirstChar 38 +/LastChar 150 +/Widths 692 0 R +/BaseFont /UVWHXA+URWGothicL-Demi +/FontDescriptor 178 0 R +>> endobj +178 0 obj << +/Ascent 756 +/CapHeight 756 +/Descent -192 +/FontName /UVWHXA+URWGothicL-Demi +/ItalicAngle 0 +/StemV 134 +/XHeight 555 +/FontBBox [-121 -251 1248 1000] +/Flags 4 +/CharSet (/ampersand/quoteright/parenleft/parenright/comma/hyphen/period/zero/one/two/three/four/five/six/seven/eight/nine/colon/A/B/C/D/E/F/G/H/I/J/L/M/O/P/R/S/T/U/W/Y/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/r/s/t/u/v/w/x/y/z/quotedblleft/quotedblright/endash) +/FontFile 179 0 R +>> endobj +692 0 obj +[680 280 380 380 0 0 280 420 280 0 560 560 560 560 560 560 560 560 560 560 280 0 0 0 0 0 0 740 580 780 700 520 480 840 680 280 480 0 440 900 0 840 560 0 580 520 420 640 0 900 0 620 0 0 0 0 0 0 0 660 660 640 660 640 280 660 600 240 260 580 240 940 600 640 660 0 320 440 300 600 560 800 560 580 460 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 480 480 0 500 ] +endobj +181 0 obj << +/Type /Pages +/Count 6 +/Parent 693 0 R +/Kids [170 0 R 187 0 R 199 0 R 237 0 R 251 0 R 266 0 R] +>> endobj +283 0 obj << +/Type /Pages +/Count 6 +/Parent 693 0 R +/Kids [273 0 R 285 0 R 305 0 R 314 0 R 324 0 R 331 0 R] +>> endobj +345 0 obj << +/Type /Pages +/Count 6 +/Parent 693 0 R +/Kids [336 0 R 349 0 R 359 0 R 373 0 R 380 0 R 392 0 R] +>> endobj +406 0 obj << +/Type /Pages +/Count 6 +/Parent 693 0 R +/Kids [400 0 R 408 0 R 414 0 R 420 0 R 426 0 R 431 0 R] +>> endobj +442 0 obj << +/Type /Pages +/Count 6 +/Parent 693 0 R +/Kids [436 0 R 444 0 R 451 0 R 459 0 R 483 0 R 497 0 R] +>> endobj +515 0 obj << +/Type /Pages +/Count 6 +/Parent 693 0 R +/Kids [504 0 R 520 0 R 525 0 R 531 0 R 544 0 R 552 0 R] +>> endobj +577 0 obj << +/Type /Pages +/Count 6 +/Parent 694 0 R +/Kids [566 0 R 583 0 R 597 0 R 605 0 R 620 0 R 627 0 R] +>> endobj +641 0 obj << +/Type /Pages +/Count 5 +/Parent 694 0 R +/Kids [636 0 R 643 0 R 652 0 R 664 0 R 675 0 R] +>> endobj +693 0 obj << +/Type /Pages +/Count 36 +/Parent 695 0 R +/Kids [181 0 R 283 0 R 345 0 R 406 0 R 442 0 R 515 0 R] +>> endobj +694 0 obj << +/Type /Pages +/Count 11 +/Parent 695 0 R +/Kids [577 0 R 641 0 R] +>> endobj +695 0 obj << +/Type /Pages +/Count 47 +/Kids [693 0 R 694 0 R] +>> endobj +696 0 obj << +/Type /Outlines +/First 7 0 R +/Last 159 0 R +/Count 6 +>> endobj +167 0 obj << +/Title 168 0 R +/A 165 0 R +/Parent 159 0 R +/Prev 163 0 R +>> endobj +163 0 obj << +/Title 164 0 R +/A 161 0 R +/Parent 159 0 R +/Next 167 0 R +>> endobj +159 0 obj << +/Title 160 0 R +/A 157 0 R +/Parent 696 0 R +/Prev 155 0 R +/First 163 0 R +/Last 167 0 R +/Count -2 +>> endobj +155 0 obj << +/Title 156 0 R +/A 153 0 R +/Parent 696 0 R +/Prev 99 0 R +/Next 159 0 R +>> endobj +151 0 obj << +/Title 152 0 R +/A 149 0 R +/Parent 99 0 R +/Prev 123 0 R +>> endobj +147 0 obj << +/Title 148 0 R +/A 145 0 R +/Parent 123 0 R +/Prev 143 0 R +>> endobj +143 0 obj << +/Title 144 0 R +/A 141 0 R +/Parent 123 0 R +/Prev 139 0 R +/Next 147 0 R +>> endobj +139 0 obj << +/Title 140 0 R +/A 137 0 R +/Parent 123 0 R +/Prev 135 0 R +/Next 143 0 R +>> endobj +135 0 obj << +/Title 136 0 R +/A 133 0 R +/Parent 123 0 R +/Prev 131 0 R +/Next 139 0 R +>> endobj +131 0 obj << +/Title 132 0 R +/A 129 0 R +/Parent 123 0 R +/Prev 127 0 R +/Next 135 0 R +>> endobj +127 0 obj << +/Title 128 0 R +/A 125 0 R +/Parent 123 0 R +/Next 131 0 R +>> endobj +123 0 obj << +/Title 124 0 R +/A 121 0 R +/Parent 99 0 R +/Prev 103 0 R +/Next 151 0 R +/First 127 0 R +/Last 147 0 R +/Count -6 +>> endobj +119 0 obj << +/Title 120 0 R +/A 117 0 R +/Parent 103 0 R +/Prev 115 0 R +>> endobj +115 0 obj << +/Title 116 0 R +/A 113 0 R +/Parent 103 0 R +/Prev 111 0 R +/Next 119 0 R +>> endobj +111 0 obj << +/Title 112 0 R +/A 109 0 R +/Parent 103 0 R +/Prev 107 0 R +/Next 115 0 R +>> endobj +107 0 obj << +/Title 108 0 R +/A 105 0 R +/Parent 103 0 R +/Next 111 0 R +>> endobj +103 0 obj << +/Title 104 0 R +/A 101 0 R +/Parent 99 0 R +/Next 123 0 R +/First 107 0 R +/Last 119 0 R +/Count -4 +>> endobj +99 0 obj << +/Title 100 0 R +/A 97 0 R +/Parent 696 0 R +/Prev 27 0 R +/Next 155 0 R +/First 103 0 R +/Last 151 0 R +/Count -3 +>> endobj +95 0 obj << +/Title 96 0 R +/A 93 0 R +/Parent 27 0 R +/Prev 91 0 R +>> endobj +91 0 obj << +/Title 92 0 R +/A 89 0 R +/Parent 27 0 R +/Prev 59 0 R +/Next 95 0 R +>> endobj +87 0 obj << +/Title 88 0 R +/A 85 0 R +/Parent 59 0 R +/Prev 83 0 R +>> endobj +83 0 obj << +/Title 84 0 R +/A 81 0 R +/Parent 59 0 R +/Prev 79 0 R +/Next 87 0 R +>> endobj +79 0 obj << +/Title 80 0 R +/A 77 0 R +/Parent 59 0 R +/Prev 75 0 R +/Next 83 0 R +>> endobj +75 0 obj << +/Title 76 0 R +/A 73 0 R +/Parent 59 0 R +/Prev 71 0 R +/Next 79 0 R +>> endobj +71 0 obj << +/Title 72 0 R +/A 69 0 R +/Parent 59 0 R +/Prev 67 0 R +/Next 75 0 R +>> endobj +67 0 obj << +/Title 68 0 R +/A 65 0 R +/Parent 59 0 R +/Prev 63 0 R +/Next 71 0 R +>> endobj +63 0 obj << +/Title 64 0 R +/A 61 0 R +/Parent 59 0 R +/Next 67 0 R +>> endobj +59 0 obj << +/Title 60 0 R +/A 57 0 R +/Parent 27 0 R +/Prev 35 0 R +/Next 91 0 R +/First 63 0 R +/Last 87 0 R +/Count -7 +>> endobj +55 0 obj << +/Title 56 0 R +/A 53 0 R +/Parent 35 0 R +/Prev 51 0 R +>> endobj +51 0 obj << +/Title 52 0 R +/A 49 0 R +/Parent 35 0 R +/Prev 47 0 R +/Next 55 0 R +>> endobj +47 0 obj << +/Title 48 0 R +/A 45 0 R +/Parent 35 0 R +/Prev 43 0 R +/Next 51 0 R +>> endobj +43 0 obj << +/Title 44 0 R +/A 41 0 R +/Parent 35 0 R +/Prev 39 0 R +/Next 47 0 R +>> endobj +39 0 obj << +/Title 40 0 R +/A 37 0 R +/Parent 35 0 R +/Next 43 0 R +>> endobj +35 0 obj << +/Title 36 0 R +/A 33 0 R +/Parent 27 0 R +/Prev 31 0 R +/Next 59 0 R +/First 39 0 R +/Last 55 0 R +/Count -5 +>> endobj +31 0 obj << +/Title 32 0 R +/A 29 0 R +/Parent 27 0 R +/Next 35 0 R +>> endobj +27 0 obj << +/Title 28 0 R +/A 25 0 R +/Parent 696 0 R +/Prev 11 0 R +/Next 99 0 R +/First 31 0 R +/Last 95 0 R +/Count -5 +>> endobj +23 0 obj << +/Title 24 0 R +/A 21 0 R +/Parent 11 0 R +/Prev 19 0 R +>> endobj +19 0 obj << +/Title 20 0 R +/A 17 0 R +/Parent 11 0 R +/Prev 15 0 R +/Next 23 0 R +>> endobj +15 0 obj << +/Title 16 0 R +/A 13 0 R +/Parent 11 0 R +/Next 19 0 R +>> endobj +11 0 obj << +/Title 12 0 R +/A 9 0 R +/Parent 696 0 R +/Prev 7 0 R +/Next 27 0 R +/First 15 0 R +/Last 23 0 R +/Count -3 +>> endobj +7 0 obj << +/Title 8 0 R +/A 5 0 R +/Parent 696 0 R +/Next 11 0 R +>> endobj +697 0 obj << +/Names [(Doc-Start) 176 0 R (Item.1) 364 0 R (Item.2) 365 0 R (Item.3) 366 0 R (Item.4) 388 0 R (Item.5) 389 0 R (Item.6) 396 0 R (Item.7) 470 0 R (Item.8) 471 0 R (application-level-interface) 303 0 R (cite.AB-OC) 480 0 R (cite.ARCH) 659 0 R (cite.BLANCHET99) 540 0 R (cite.BOEHM) 579 0 R (cite.CGSI) 493 0 R (cite.CHOI99) 541 0 R (cite.CPy) 661 0 R (cite.D04.2) 550 0 R (cite.D05.1) 262 0 R (cite.D05.3) 516 0 R (cite.D05.4) 517 0 R (cite.DEL) 617 0 R (cite.DETREVILLE90) 593 0 R (cite.DHRY) 518 0 R (cite.FRANZ02) 542 0 R (cite.GC) 581 0 R (cite.GCSURV) 580 0 R (cite.JIKES) 595 0 R (cite.LIMBO) 476 0 R (cite.MAS) 494 0 R (cite.MMTK) 578 0 R (cite.MRD) 671 0 R (cite.PICOIL) 322 0 R (cite.PLTWebserver) 479 0 R (cite.PMTPM) 495 0 R (cite.PYLIB) 672 0 R (cite.R5RS) 481 0 R (cite.RCPFCC) 679 0 R (cite.SEDA) 474 0 R (cite.SLP) 390 0 R (cite.SLP0) 301 0 R (cite.SQUEAK) 563 0 R (cite.Seaside) 478 0 R (cite.Twisted) 475 0 R (cite.VMC) 271 0 R (cite.von-Behren-et-al) 477 0 R (composability) 371 0 R (conclusion) 640 0 R (coroutine-cloning) 418 0 R (coroutine-pickling) 347 0 R (coroutines) 346 0 R (escape-analysis-and-stack-allocation) 535 0 R (executive-summary) 255 0 R (figure.1) 631 0 R (finding-roots) 357 0 R (function-inlining) 514 0 R (glossary-of-abbreviations) 648 0 R (greenlets) 398 0 R (id16) 472 0 R (id51) 625 0 R (id7) 320 0 R (interface-to-explicit-stack-manipulations) 328 0 R (introduction) 277 0 R (introduction-stackless-features-for-rpython-programs) 293 0 R (malloc-removal) 529 0 R (memory-management) 356 0 R (microbenchmarks-of-stackless-features) 370 0 R (optimizations) 511 0 R (optimizations-and-memory-management) 264 0 R (page.1) 175 0 R (page.10) 316 0 R (page.11) 326 0 R (page.12) 333 0 R (page.13) 338 0 R (page.14) 351 0 R (page.15) 361 0 R (page.16) 375 0 R (page.17) 382 0 R (page.18) 394 0 R (page.19) 402 0 R (page.2) 189 0 R (page.20) 410 0 R (page.21) 416 0 R (page.22) 422 0 R (page.23) 428 0 R (page.24) 433 0 R (page.25) 438 0 R (page.26) 446 0 R (page.27) 453 0 R (page.28) 461 0 R (page.29) 485 0 R (page.3) 201 0 R (page.30) 499 0 R (page.31) 506 0 R (page.32) 522 0 R (page.33) 527 0 R (page.34) 533 0 R (page.35) 546 0 R (page.36) 554 0 R (page.37) 568 0 R (page.38) 585 0 R (page.39) 599 0 R (page.4) 239 0 R (page.40) 607 0 R (page.41) 622 0 R (page.42) 629 0 R (page.43) 638 0 R (page.44) 645 0 R (page.45) 654 0 R (page.46) 666 0 R (page.47) 197 0 R (page.5) 253 0 R (page.6) 268 0 R (page.7) 275 0 R (page.8) 287 0 R (page.9) 307 0 R (partner-acronyms) 656 0 R (performance-future-work) 616 0 R (performance-impact) 344 0 R (pointer-tagging) 539 0 R (practical-uses-of-massive-parallelism) 457 0 R (purpose-of-this-document) 278 0 R (reference-counting) 574 0 R (related-documents) 280 0 R (related-work) 302 0 R (resume-points) 341 0 R (saving-and-resuming-frames) 309 0 R (scope-of-this-document) 279 0 R (section*.1) 194 0 R (section*.10) 601 0 R (section*.11) 602 0 R (section*.12) 609 0 R (section*.13) 658 0 R (section*.2) 196 0 R (section*.3) 203 0 R (section*.4) 378 0 R (section*.5) 387 0 R (section*.6) 397 0 R (section*.7) 405 0 R (section*.8) 412 0 R (section*.9) 424 0 R (section.1) 6 0 R (section.2) 10 0 R (section.3) 26 0 R (section.4) 98 0 R (section.5) 154 0 R (section.6) 158 0 R (stackless-features) 263 0 R (stackless-transformation) 300 0 R (subsection.2.1) 14 0 R (subsection.2.2) 18 0 R (subsection.2.3) 22 0 R (subsection.3.1) 30 0 R (subsection.3.2) 34 0 R (subsection.3.3) 58 0 R (subsection.3.4) 90 0 R (subsection.3.5) 94 0 R (subsection.4.1) 102 0 R (subsection.4.2) 122 0 R (subsection.4.3) 150 0 R (subsection.6.1) 162 0 R (subsection.6.2) 166 0 R (subsubsection.3.2.1) 38 0 R (subsubsection.3.2.2) 42 0 R (subsubsection.3.2.3) 46 0 R (subsubsection.3.2.4) 50 0 R (subsubsection.3.2.5) 54 0 R (subsubsection.3.3.1) 62 0 R (subsubsection.3.3.2) 66 0 R (subsubsection.3.3.3) 70 0 R (subsubsection.3.3.4) 74 0 R (subsubsection.3.3.5) 78 0 R (subsubsection.3.3.6) 82 0 R (subsubsection.3.3.7) 86 0 R (subsubsection.4.1.1) 106 0 R (subsubsection.4.1.2) 110 0 R (subsubsection.4.1.3) 114 0 R (subsubsection.4.1.4) 118 0 R (subsubsection.4.2.1) 126 0 R (subsubsection.4.2.2) 130 0 R (subsubsection.4.2.3) 134 0 R (subsubsection.4.2.4) 138 0 R (subsubsection.4.2.5) 142 0 R (subsubsection.4.2.6) 146 0 R (table.1) 177 0 R (table.2) 195 0 R (table.3) 363 0 R (table.4) 441 0 R (table.5) 448 0 R (table.6) 449 0 R (table.7) 624 0 R (table.8) 650 0 R (table.9) 657 0 R (tasklets-and-channels) 384 0 R (technical-abbreviations) 649 0 R (the-gc-construction-and-testing-framework) 564 0 R (the-gc-transformer) 562 0 R (the-mark-and-sweep-collector) 594 0 R (the-stackless-transformation) 299 0 R (unbounded-stack) 321 0 R (using-the-conservative-boehm-collector) 572 0 R] +/Limits [(Doc-Start) (using-the-conservative-boehm-collector)] +>> endobj +698 0 obj << +/Kids [697 0 R] +>> endobj +699 0 obj << +/Dests 698 0 R +>> endobj +700 0 obj << +/Type /Catalog +/Pages 695 0 R +/Outlines 696 0 R +/Names 699 0 R +/PageMode /UseOutlines +/OpenAction 169 0 R +>> endobj +701 0 obj << +/Author()/Title()/Subject()/Creator(LaTeX with hyperref package)/Producer(pdfeTeX-1.21a)/Keywords() +/CreationDate (D:20061215142106+01'00') +/PTEX.Fullbanner (This is pdfeTeX, Version 3.141592-1.21a-2.2 (Web2C 7.5.4) kpathsea version 3.5.4) +>> endobj +xref +0 702 +0000000001 65535 f +0000000002 00000 f +0000000003 00000 f +0000000004 00000 f +0000000000 00000 f +0000000009 00000 n +0000039117 00000 n +0000378110 00000 n +0000000054 00000 n +0000000089 00000 n +0000044649 00000 n +0000377987 00000 n +0000000134 00000 n +0000000165 00000 n +0000044774 00000 n +0000377913 00000 n +0000000216 00000 n +0000000259 00000 n +0000044899 00000 n +0000377826 00000 n +0000000310 00000 n +0000000351 00000 n +0000045024 00000 n +0000377752 00000 n +0000000402 00000 n +0000000438 00000 n +0000050332 00000 n +0000377627 00000 n +0000000484 00000 n +0000000521 00000 n +0000050457 00000 n +0000377553 00000 n +0000000572 00000 n +0000000644 00000 n +0000050645 00000 n +0000377429 00000 n +0000000695 00000 n +0000000742 00000 n +0000054752 00000 n +0000377355 00000 n +0000000798 00000 n +0000000843 00000 n +0000063997 00000 n +0000377268 00000 n +0000000899 00000 n +0000000937 00000 n +0000064122 00000 n +0000377181 00000 n +0000000993 00000 n +0000001053 00000 n +0000072275 00000 n +0000377094 00000 n +0000001109 00000 n +0000001141 00000 n +0000072400 00000 n +0000377020 00000 n +0000001197 00000 n +0000001234 00000 n +0000082242 00000 n +0000376896 00000 n +0000001285 00000 n +0000001331 00000 n +0000086082 00000 n +0000376822 00000 n +0000001387 00000 n +0000001416 00000 n +0000089496 00000 n +0000376735 00000 n +0000001472 00000 n +0000001512 00000 n +0000092833 00000 n +0000376648 00000 n +0000001568 00000 n +0000001596 00000 n +0000096814 00000 n +0000376561 00000 n +0000001652 00000 n +0000001689 00000 n +0000103928 00000 n +0000376474 00000 n +0000001745 00000 n +0000001781 00000 n +0000107507 00000 n +0000376387 00000 n +0000001837 00000 n +0000001869 00000 n +0000116981 00000 n +0000376313 00000 n +0000001925 00000 n +0000001981 00000 n +0000125268 00000 n +0000376226 00000 n +0000002032 00000 n +0000002088 00000 n +0000131358 00000 n +0000376152 00000 n +0000002139 00000 n +0000002170 00000 n +0000144376 00000 n +0000376023 00000 n +0000002216 00000 n +0000002271 00000 n +0000144500 00000 n +0000375906 00000 n +0000002323 00000 n +0000002356 00000 n +0000149065 00000 n +0000375827 00000 n +0000002413 00000 n +0000002450 00000 n +0000152339 00000 n +0000375734 00000 n +0000002507 00000 n +0000002541 00000 n +0000157184 00000 n +0000375641 00000 n +0000002598 00000 n +0000002654 00000 n +0000162136 00000 n +0000375562 00000 n +0000002711 00000 n +0000002746 00000 n +0000167656 00000 n +0000375431 00000 n +0000002798 00000 n +0000002835 00000 n +0000167782 00000 n +0000375352 00000 n +0000002892 00000 n +0000002930 00000 n +0000172964 00000 n +0000375259 00000 n +0000002987 00000 n +0000003045 00000 n +0000173089 00000 n +0000375166 00000 n +0000003102 00000 n +0000003140 00000 n +0000178682 00000 n +0000375073 00000 n +0000003197 00000 n +0000003258 00000 n +0000187564 00000 n +0000374980 00000 n +0000003315 00000 n +0000003363 00000 n +0000187690 00000 n +0000374901 00000 n +0000003420 00000 n +0000003468 00000 n +0000192393 00000 n +0000374823 00000 n +0000003520 00000 n +0000003552 00000 n +0000281679 00000 n +0000374731 00000 n +0000003599 00000 n +0000003629 00000 n +0000285579 00000 n +0000374613 00000 n +0000003676 00000 n +0000003721 00000 n +0000285705 00000 n +0000374534 00000 n +0000003773 00000 n +0000003817 00000 n +0000289819 00000 n +0000374455 00000 n +0000003869 00000 n +0000003906 00000 n +0000005256 00000 n +0000005378 00000 n +0000007509 00000 n +0000019084 00000 n +0000003958 00000 n +0000018895 00000 n +0000018958 00000 n +0000019021 00000 n +0000372350 00000 n +0000359605 00000 n +0000372179 00000 n +0000373178 00000 n +0000007226 00000 n +0000018736 00000 n +0000018792 00000 n +0000018872 00000 n +0000022140 00000 n +0000021592 00000 n +0000019213 00000 n +0000021888 00000 n +0000358303 00000 n +0000343970 00000 n +0000358133 00000 n +0000021734 00000 n +0000021951 00000 n +0000022014 00000 n +0000022077 00000 n +0000301277 00000 n +0000031079 00000 n +0000025201 00000 n +0000022269 00000 n +0000030953 00000 n +0000025599 00000 n +0000031016 00000 n +0000025753 00000 n +0000025908 00000 n +0000026063 00000 n +0000026223 00000 n +0000026383 00000 n +0000026543 00000 n +0000026698 00000 n +0000026858 00000 n +0000027018 00000 n +0000027183 00000 n +0000027349 00000 n +0000027515 00000 n +0000027681 00000 n +0000027846 00000 n +0000028006 00000 n +0000028172 00000 n +0000028338 00000 n +0000028503 00000 n +0000028669 00000 n +0000028835 00000 n +0000029001 00000 n +0000029166 00000 n +0000029326 00000 n +0000029486 00000 n +0000029640 00000 n +0000029800 00000 n +0000029966 00000 n +0000030132 00000 n +0000030297 00000 n +0000030463 00000 n +0000030623 00000 n +0000030789 00000 n +0000034365 00000 n +0000032485 00000 n +0000031208 00000 n +0000034302 00000 n +0000032699 00000 n +0000032853 00000 n +0000033019 00000 n +0000033185 00000 n +0000033348 00000 n +0000033514 00000 n +0000033673 00000 n +0000033828 00000 n +0000033982 00000 n +0000034142 00000 n +0000039178 00000 n +0000038171 00000 n +0000034494 00000 n +0000038991 00000 n +0000038337 00000 n +0000039054 00000 n +0000038491 00000 n +0000343650 00000 n +0000342260 00000 n +0000343489 00000 n +0000038648 00000 n +0000038811 00000 n +0000290509 00000 n +0000050269 00000 n +0000144313 00000 n +0000041956 00000 n +0000041435 00000 n +0000039320 00000 n +0000041893 00000 n +0000041585 00000 n +0000041739 00000 n +0000301841 00000 n +0000045086 00000 n +0000043899 00000 n +0000042085 00000 n +0000044523 00000 n +0000044057 00000 n +0000044586 00000 n +0000044711 00000 n +0000044836 00000 n +0000044961 00000 n +0000044211 00000 n +0000044366 00000 n +0000373295 00000 n +0000050707 00000 n +0000048861 00000 n +0000045228 00000 n +0000050206 00000 n +0000049051 00000 n +0000341484 00000 n +0000331012 00000 n +0000341310 00000 n +0000049205 00000 n +0000050394 00000 n +0000049360 00000 n +0000049519 00000 n +0000049689 00000 n +0000049859 00000 n +0000050033 00000 n +0000050519 00000 n +0000050582 00000 n +0000301590 00000 n +0000131295 00000 n +0000082179 00000 n +0000054814 00000 n +0000054330 00000 n +0000050849 00000 n +0000054626 00000 n +0000054472 00000 n +0000054689 00000 n +0000330204 00000 n +0000313981 00000 n +0000330033 00000 n +0000059862 00000 n +0000059045 00000 n +0000054969 00000 n +0000059675 00000 n +0000059203 00000 n +0000059356 00000 n +0000059514 00000 n +0000059738 00000 n +0000059800 00000 n +0000296369 00000 n +0000064184 00000 n +0000063469 00000 n +0000060004 00000 n +0000063934 00000 n +0000063619 00000 n +0000064059 00000 n +0000063772 00000 n +0000067327 00000 n +0000066969 00000 n +0000064339 00000 n +0000067264 00000 n +0000067111 00000 n +0000072462 00000 n +0000071344 00000 n +0000067495 00000 n +0000072149 00000 n +0000071510 00000 n +0000071663 00000 n +0000072212 00000 n +0000071820 00000 n +0000071985 00000 n +0000072337 00000 n +0000373412 00000 n +0000082304 00000 n +0000096751 00000 n +0000077207 00000 n +0000076344 00000 n +0000072617 00000 n +0000077144 00000 n +0000076510 00000 n +0000076663 00000 n +0000076827 00000 n +0000076987 00000 n +0000167593 00000 n +0000302109 00000 n +0000082367 00000 n +0000081018 00000 n +0000077362 00000 n +0000081864 00000 n +0000081184 00000 n +0000081927 00000 n +0000081990 00000 n +0000082053 00000 n +0000082116 00000 n +0000081337 00000 n +0000081521 00000 n +0000081704 00000 n +0000116918 00000 n +0000107445 00000 n +0000086207 00000 n +0000085556 00000 n +0000082509 00000 n +0000086019 00000 n +0000085706 00000 n +0000085859 00000 n +0000086144 00000 n +0000089747 00000 n +0000088750 00000 n +0000086362 00000 n +0000089370 00000 n +0000088908 00000 n +0000089433 00000 n +0000089061 00000 n +0000089214 00000 n +0000089558 00000 n +0000089621 00000 n +0000089684 00000 n +0000301527 00000 n +0000092895 00000 n +0000092286 00000 n +0000089902 00000 n +0000092581 00000 n +0000092428 00000 n +0000092644 00000 n +0000092707 00000 n +0000092770 00000 n +0000096939 00000 n +0000096225 00000 n +0000093037 00000 n +0000096688 00000 n +0000096375 00000 n +0000096528 00000 n +0000096876 00000 n +0000373529 00000 n +0000099839 00000 n +0000099418 00000 n +0000097094 00000 n +0000099713 00000 n +0000099560 00000 n +0000099776 00000 n +0000103989 00000 n +0000103507 00000 n +0000099994 00000 n +0000103802 00000 n +0000103649 00000 n +0000103865 00000 n +0000107568 00000 n +0000107024 00000 n +0000104157 00000 n +0000107319 00000 n +0000107166 00000 n +0000107382 00000 n +0000109598 00000 n +0000109240 00000 n +0000107736 00000 n +0000109535 00000 n +0000109382 00000 n +0000112855 00000 n +0000112497 00000 n +0000109740 00000 n +0000112792 00000 n +0000112639 00000 n +0000117106 00000 n +0000116387 00000 n +0000113010 00000 n +0000116855 00000 n +0000116537 00000 n +0000116690 00000 n +0000117043 00000 n +0000373646 00000 n +0000120977 00000 n +0000120493 00000 n +0000117261 00000 n +0000120788 00000 n +0000120635 00000 n +0000120851 00000 n +0000120914 00000 n +0000125330 00000 n +0000124502 00000 n +0000121119 00000 n +0000125142 00000 n +0000124660 00000 n +0000124813 00000 n +0000124978 00000 n +0000125205 00000 n +0000131420 00000 n +0000129418 00000 n +0000125485 00000 n +0000131044 00000 n +0000129624 00000 n +0000129777 00000 n +0000129932 00000 n +0000130090 00000 n +0000130247 00000 n +0000130415 00000 n +0000130574 00000 n +0000130737 00000 n +0000131107 00000 n +0000131169 00000 n +0000131232 00000 n +0000130891 00000 n +0000301465 00000 n +0000301778 00000 n +0000296118 00000 n +0000301904 00000 n +0000301715 00000 n +0000296432 00000 n +0000290008 00000 n +0000301340 00000 n +0000136973 00000 n +0000135639 00000 n +0000131575 00000 n +0000136910 00000 n +0000135829 00000 n +0000135982 00000 n +0000136134 00000 n +0000136286 00000 n +0000136443 00000 n +0000136599 00000 n +0000136754 00000 n +0000290258 00000 n +0000296181 00000 n +0000296495 00000 n +0000139463 00000 n +0000138773 00000 n +0000137128 00000 n +0000139400 00000 n +0000138931 00000 n +0000139084 00000 n +0000139243 00000 n +0000144625 00000 n +0000143136 00000 n +0000139592 00000 n +0000144250 00000 n +0000143318 00000 n +0000143471 00000 n +0000143627 00000 n +0000143784 00000 n +0000144438 00000 n +0000143939 00000 n +0000144095 00000 n +0000144562 00000 n +0000373763 00000 n +0000290572 00000 n +0000290634 00000 n +0000295804 00000 n +0000149128 00000 n +0000148707 00000 n +0000144754 00000 n +0000149002 00000 n +0000148849 00000 n +0000152402 00000 n +0000151918 00000 n +0000149270 00000 n +0000152213 00000 n +0000152060 00000 n +0000152276 00000 n +0000157309 00000 n +0000156261 00000 n +0000152557 00000 n +0000157058 00000 n +0000156427 00000 n +0000157121 00000 n +0000156580 00000 n +0000156742 00000 n +0000156900 00000 n +0000157247 00000 n +0000290132 00000 n +0000290321 00000 n +0000295867 00000 n +0000162199 00000 n +0000161449 00000 n +0000157451 00000 n +0000162073 00000 n +0000161607 00000 n +0000161760 00000 n +0000161916 00000 n +0000290446 00000 n +0000167845 00000 n +0000166205 00000 n +0000162341 00000 n +0000167530 00000 n +0000166395 00000 n +0000166548 00000 n +0000166705 00000 n +0000166862 00000 n +0000167019 00000 n +0000167184 00000 n +0000167342 00000 n +0000167719 00000 n +0000301652 00000 n +0000178619 00000 n +0000173152 00000 n +0000171728 00000 n +0000167974 00000 n +0000172839 00000 n +0000171910 00000 n +0000172063 00000 n +0000172218 00000 n +0000172902 00000 n +0000172372 00000 n +0000173026 00000 n +0000172529 00000 n +0000172686 00000 n +0000373880 00000 n +0000296244 00000 n +0000290195 00000 n +0000295930 00000 n +0000295993 00000 n +0000178743 00000 n +0000177239 00000 n +0000173307 00000 n +0000178556 00000 n +0000177429 00000 n +0000177582 00000 n +0000177745 00000 n +0000177920 00000 n +0000178094 00000 n +0000178246 00000 n +0000178401 00000 n +0000295741 00000 n +0000187501 00000 n +0000296055 00000 n +0000182891 00000 n +0000182225 00000 n +0000178872 00000 n +0000182702 00000 n +0000182375 00000 n +0000182765 00000 n +0000182828 00000 n +0000182528 00000 n +0000187753 00000 n +0000186589 00000 n +0000183020 00000 n +0000187375 00000 n +0000186755 00000 n +0000187438 00000 n +0000313455 00000 n +0000304029 00000 n +0000313284 00000 n +0000186908 00000 n +0000187062 00000 n +0000187220 00000 n +0000187627 00000 n +0000295678 00000 n +0000193429 00000 n +0000192455 00000 n +0000191910 00000 n +0000187921 00000 n +0000192205 00000 n +0000192052 00000 n +0000192268 00000 n +0000192331 00000 n +0000277734 00000 n +0000193287 00000 n +0000192597 00000 n +0000277607 00000 n +0000277454 00000 n +0000277670 00000 n +0000277200 00000 n +0000277384 00000 n +0000277431 00000 n +0000281742 00000 n +0000281259 00000 n +0000277876 00000 n +0000281554 00000 n +0000281401 00000 n +0000281617 00000 n +0000373997 00000 n +0000285831 00000 n +0000284995 00000 n +0000281871 00000 n +0000285453 00000 n +0000285145 00000 n +0000285298 00000 n +0000285516 00000 n +0000285642 00000 n +0000285768 00000 n +0000290697 00000 n +0000289018 00000 n +0000285960 00000 n +0000289693 00000 n +0000289176 00000 n +0000289756 00000 n +0000289882 00000 n +0000289945 00000 n +0000290069 00000 n +0000289329 00000 n +0000290384 00000 n +0000289522 00000 n +0000296621 00000 n +0000294441 00000 n +0000290839 00000 n +0000295615 00000 n +0000294615 00000 n +0000294768 00000 n +0000295003 00000 n +0000295238 00000 n +0000296307 00000 n +0000296558 00000 n +0000295440 00000 n +0000301967 00000 n +0000299774 00000 n +0000296763 00000 n +0000299964 00000 n +0000300117 00000 n +0000301403 00000 n +0000300309 00000 n +0000300499 00000 n +0000300676 00000 n +0000300866 00000 n +0000301046 00000 n +0000302141 00000 n +0000313749 00000 n +0000330684 00000 n +0000341884 00000 n +0000343883 00000 n +0000343859 00000 n +0000358903 00000 n +0000372800 00000 n +0000374106 00000 n +0000374224 00000 n +0000374310 00000 n +0000374380 00000 n +0000378182 00000 n +0000383017 00000 n +0000383056 00000 n +0000383094 00000 n +0000383224 00000 n +trailer +<< +/Size 702 +/Root 700 0 R +/Info 701 0 R +/ID [<809FB1048C874E80C1662D534069FE88> <809FB1048C874E80C1662D534069FE88>] +>> +startxref +383487 +%%EOF From cfbolz at codespeak.net Fri Dec 15 14:28:37 2006 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Fri, 15 Dec 2006 14:28:37 +0100 (CET) Subject: [pypy-svn] r35798 - pypy/dist/pypy/doc Message-ID: <20061215132837.246E81008A@code0.codespeak.net> Author: cfbolz Date: Fri Dec 15 14:28:35 2006 New Revision: 35798 Modified: pypy/dist/pypy/doc/index-report.txt Log: change text and link for D07 report to say that it is complete now. Modified: pypy/dist/pypy/doc/index-report.txt ============================================================================== --- pypy/dist/pypy/doc/index-report.txt (original) +++ pypy/dist/pypy/doc/index-report.txt Fri Dec 15 14:28:35 2006 @@ -16,11 +16,10 @@ the second phase of the EU project, summarizing and detailing technical, research, dissemination and community aspects. Feedback is very welcome! -`Draft D07.1 Massive Parallelism and Translation Aspects`_ is an interim +`Draft D07.1 Massive Parallelism and Translation Aspects`_ is a nearly finished version of a report about PyPy's optimization efforts, garbage collectors and -massive parallelism (stackless) features. The report is not complete -(especially the stackless part is still missing), all feedback to it is -extremely welcome! +massive parallelism (stackless) features. The report is basically done, however +we are still incorporating feedback. `Draft D09.1 Constraint Solving and Semantic Web`_ is an interim version of a report about PyPy's logic programming and constraint solving features, as well @@ -68,6 +67,6 @@ .. _`D05.3 Implementation with Translation Aspects`: http://codespeak.net/svn/pypy/extradoc/eu-report/D05.3_Publish_on_implementation_with_translation_aspects.pdf .. _`D05.4 Encapsulating Low Level Aspects`: http://codespeak.net/svn/pypy/extradoc/eu-report/D05.4_Publish_on_encapsulating_low_level_language_aspects.pdf .. _`D14.1 Report about Milestone/Phase 1`: http://codespeak.net/svn/pypy/extradoc/eu-report/D14.1_Report_about_Milestone_Phase_1.pdf -.. _`Draft D07.1 Massive Parallelism and Translation Aspects`: http://codespeak.net/pypy/extradoc/eu-report/D07.1_Massive_Parallelism_and_Translation_Aspects-interim-2006-07-25.pdf +.. _`Draft D07.1 Massive Parallelism and Translation Aspects`: http://codespeak.net/pypy/extradoc/eu-report/D07.1_Massive_Parallelism_and_Translation_Aspects-interim-2006-12-15.pdf .. _`Draft D09.1 Constraint Solving and Semantic Web`: http://codespeak.net/pypy/extradoc/eu-report/D09.1_Constraint_Solving_and_Semantic_Web-interim-2006-07-28.pdf .. _`D14.3 Report about Milestone/Phase 2`: http://codespeak.net/pypy/extradoc/eu-report/D14.3_Report_about_Milestone_Phase_2-final-2006-08-03.pdf From fijal at codespeak.net Fri Dec 15 14:41:42 2006 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 15 Dec 2006 14:41:42 +0100 (CET) Subject: [pypy-svn] r35799 - pypy/extradoc/sprintinfo/leysin-winter-2007 Message-ID: <20061215134142.C19101008B@code0.codespeak.net> Author: fijal Date: Fri Dec 15 14:41:41 2006 New Revision: 35799 Modified: pypy/extradoc/sprintinfo/leysin-winter-2007/people.txt Log: Added my possible dates. Modified: pypy/extradoc/sprintinfo/leysin-winter-2007/people.txt ============================================================================== --- pypy/extradoc/sprintinfo/leysin-winter-2007/people.txt (original) +++ pypy/extradoc/sprintinfo/leysin-winter-2007/people.txt Fri Dec 15 14:41:41 2006 @@ -19,6 +19,7 @@ Michael Hudson 7th-15th Ermina Niko Matsakis 9th-14th Ermina Antonio Cuni 7th-15th Ermina +Maciej Fijalkowski 5th?-17th? Ermina ==================== ============== ===================== People on the following list were present at previous sprints: @@ -46,7 +47,6 @@ Carl Friedrich Bolz ? ? Richard Emslie ? ? Johan Hahn ? ? -Maciej Fijalkowski ? ? Stephan Diehl ? ? Niko Matsakis ? ? Leonardo Santagada ? ? From arigo at codespeak.net Fri Dec 15 14:58:45 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 15 Dec 2006 14:58:45 +0100 (CET) Subject: [pypy-svn] r35800 - pypy/dist/pypy/doc Message-ID: <20061215135845.4CDD71007B@code0.codespeak.net> Author: arigo Date: Fri Dec 15 14:58:43 2006 New Revision: 35800 Modified: pypy/dist/pypy/doc/index-report.txt pypy/dist/pypy/doc/news.txt Log: News, and add a link to the annex. Modified: pypy/dist/pypy/doc/index-report.txt ============================================================================== --- pypy/dist/pypy/doc/index-report.txt (original) +++ pypy/dist/pypy/doc/index-report.txt Fri Dec 15 14:58:43 2006 @@ -16,10 +16,10 @@ the second phase of the EU project, summarizing and detailing technical, research, dissemination and community aspects. Feedback is very welcome! -`Draft D07.1 Massive Parallelism and Translation Aspects`_ is a nearly finished -version of a report about PyPy's optimization efforts, garbage collectors and -massive parallelism (stackless) features. The report is basically done, however -we are still incorporating feedback. +`D07.1 Massive Parallelism and Translation Aspects`_ is a report about +PyPy's optimization efforts, garbage collectors and massive parallelism +(stackless) features. This report refers to the paper `PyPy's approach +to virtual machine construction`_. `Draft D09.1 Constraint Solving and Semantic Web`_ is an interim version of a report about PyPy's logic programming and constraint solving features, as well @@ -67,6 +67,7 @@ .. _`D05.3 Implementation with Translation Aspects`: http://codespeak.net/svn/pypy/extradoc/eu-report/D05.3_Publish_on_implementation_with_translation_aspects.pdf .. _`D05.4 Encapsulating Low Level Aspects`: http://codespeak.net/svn/pypy/extradoc/eu-report/D05.4_Publish_on_encapsulating_low_level_language_aspects.pdf .. _`D14.1 Report about Milestone/Phase 1`: http://codespeak.net/svn/pypy/extradoc/eu-report/D14.1_Report_about_Milestone_Phase_1.pdf -.. _`Draft D07.1 Massive Parallelism and Translation Aspects`: http://codespeak.net/pypy/extradoc/eu-report/D07.1_Massive_Parallelism_and_Translation_Aspects-interim-2006-12-15.pdf +.. _`D07.1 Massive Parallelism and Translation Aspects`: http://codespeak.net/pypy/extradoc/eu-report/D07.1_Massive_Parallelism_and_Translation_Aspects-interim-2006-12-15.pdf .. _`Draft D09.1 Constraint Solving and Semantic Web`: http://codespeak.net/pypy/extradoc/eu-report/D09.1_Constraint_Solving_and_Semantic_Web-interim-2006-07-28.pdf .. _`D14.3 Report about Milestone/Phase 2`: http://codespeak.net/pypy/extradoc/eu-report/D14.3_Report_about_Milestone_Phase_2-final-2006-08-03.pdf +.. _`PyPy's approach to virtual machine construction`: http://codespeak.net/svn/pypy/extradoc/talk/dls2006/pypy-vm-construction.pdf Modified: pypy/dist/pypy/doc/news.txt ============================================================================== --- pypy/dist/pypy/doc/news.txt (original) +++ pypy/dist/pypy/doc/news.txt Fri Dec 15 14:58:43 2006 @@ -39,6 +39,16 @@ .. _`"summer" job with PyPy`: http://codespeak.net/pypy/dist/pypy/doc/summer-of-pypy.html +Massive Parallelism and Translation Aspects +======================================================== + +Our next big `EU report`_ about Stackless features, optimizations, and +memory management is finished. You can download it `as pdf`_. + +.. _`EU report`: index-report.html +.. _`as pdf`: http://codespeak.net/pypy/extradoc/eu-report/D07.1_Massive_Parallelism_and_Translation_Aspects-interim-2006-12-15.pdf + + Duesseldorf sprint #2, 30th October - 5th November over ================================================================== From pedronis at codespeak.net Fri Dec 15 15:06:49 2006 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Fri, 15 Dec 2006 15:06:49 +0100 (CET) Subject: [pypy-svn] r35801 - pypy/extradoc/talk/dls2006 Message-ID: <20061215140649.38C101007C@code0.codespeak.net> Author: pedronis Date: Fri Dec 15 15:06:48 2006 New Revision: 35801 Modified: pypy/extradoc/talk/dls2006/talk.txt Log: typo Modified: pypy/extradoc/talk/dls2006/talk.txt ============================================================================== --- pypy/extradoc/talk/dls2006/talk.txt (original) +++ pypy/extradoc/talk/dls2006/talk.txt Fri Dec 15 15:06:48 2006 @@ -5,7 +5,7 @@ ================================================= :Authors: Armin Rigo, Samuele Pedroni -:Date: 23 October 2006 / 24 Octorber 2006 +:Date: 23 October 2006 / 24 October 2006 :Location: DLS'06 OOPSLA Portland OR / Intel Hillsboro OR PyPy From guido at codespeak.net Fri Dec 15 15:29:40 2006 From: guido at codespeak.net (guido at codespeak.net) Date: Fri, 15 Dec 2006 15:29:40 +0100 (CET) Subject: [pypy-svn] r35803 - pypy/dist/pypy/tool/build/bin Message-ID: <20061215142940.90C771007F@code0.codespeak.net> Author: guido Date: Fri Dec 15 15:29:38 2006 New Revision: 35803 Modified: pypy/dist/pypy/tool/build/bin/client Log: Fixed some typos and such (after actually testing), some small changes in output (prints). Modified: pypy/dist/pypy/tool/build/bin/client ============================================================================== --- pypy/dist/pypy/tool/build/bin/client (original) +++ pypy/dist/pypy/tool/build/bin/client Fri Dec 15 15:29:38 2006 @@ -4,7 +4,6 @@ import path import sys import random -import traceback from pypy.tool.build import config as buildconfig from py.execnet import SshGateway, PopenGateway @@ -15,9 +14,14 @@ def compile(wc, compileinfo): code = """\ import sys +import os +import traceback # interpolating the path -sys.path = [%r] + sys.path +pypath = %r + +sys.path = [pypath] + sys.path +os.chdir(pypath) # nasty, interpolating a large chunk of code (OutputBuffer) %s @@ -27,8 +31,12 @@ log = open('/tmp/buildclient.log', 'a') outbuffer = OutputBuffer(log) +old_stdout = sys.__stdout__ +old_stderr = sys.__stderr__ sys.stdout = outbuffer sys.stderr = outbuffer +sys.__stdout__ = outbuffer +sys.__stderr__ = outbuffer try: try: from pypy.interpreter.error import OperationError @@ -59,10 +67,13 @@ else: channel.send(str(udir)) finally: + sys.__stdout__ = old_stdout + sys.__stderr__ = old_stderr sys.stdout = sys.__stdout__ sys.stderr = sys.__stderr__ log.close() channel.send(outbuffer.getvalue()) +channel.close() """ gw = PopenGateway() buffercode = py.magic.autopath().dirpath().dirpath()\ @@ -71,6 +82,7 @@ channel = gw.remote_exec(interpolated) upath = channel.receive() output = channel.receive() + channel.close() return upath, output @@ -130,21 +142,19 @@ print 'refusing compilation' continue # XXX we should compile here, using data dict for info - print 'compilation requested for %s\nbuilding...\n' % (request,) + print 'compilation requested for %s' % (request,) # subversion checkout print 'checking out %s@%s' % (request.svnurl, request.normalized_rev) - #temp = tempdir() - #svnwc = py.path.svnwc(temp) - #svnwc.checkout(request.svnurl) - #svnwc.update(request.normalized_rev) - svnwc = py.path.svnwc('/tmp/buildtemp-1') + temp = tempdir() + svnwc = py.path.svnwc(temp) + svnwc.checkout(request.svnurl) + svnwc.update(request.normalized_rev) try: print 'starting compilation' upath, log = compile(svnwc, request.compileinfo) - print 'compilation done' except KeyboardInterrupt: print 'quitting...' break @@ -152,14 +162,15 @@ if upath: # send over zip data, end with a None print 'compilation successful, sending to server' - zip_result(py.path.local(udir), channel) + zip_result(py.path.local(upath), channel) else: - print 'compilation failed, sending log' + print 'compilation failed, notifying server' # just send the None channel.send(None) # send over logs - channel.send(buffer.getvalue()) + print 'sending log' + channel.send(log) print 'done with compilation, waiting for next' except EOFError: From stephan at codespeak.net Fri Dec 15 15:59:42 2006 From: stephan at codespeak.net (stephan at codespeak.net) Date: Fri, 15 Dec 2006 15:59:42 +0100 (CET) Subject: [pypy-svn] r35805 - in pypy/dist/pypy/lib: . app_test test2 Message-ID: <20061215145942.E0E741007F@code0.codespeak.net> Author: stephan Date: Fri Dec 15 15:59:41 2006 New Revision: 35805 Added: pypy/dist/pypy/lib/app_test/ pypy/dist/pypy/lib/app_test/__init__.py - copied unchanged from r35791, pypy/dist/pypy/lib/test2/__init__.py pypy/dist/pypy/lib/app_test/autopath.py - copied unchanged from r35791, pypy/dist/pypy/lib/test2/autopath.py pypy/dist/pypy/lib/app_test/inprogress_test_binascii_extra.py - copied unchanged from r35791, pypy/dist/pypy/lib/test2/inprogress_test_binascii_extra.py pypy/dist/pypy/lib/app_test/no_test_pickle_extra.py - copied unchanged from r35791, pypy/dist/pypy/lib/test2/no_test_pickle_extra.py pypy/dist/pypy/lib/app_test/test_binascii.py - copied unchanged from r35791, pypy/dist/pypy/lib/test2/test_binascii.py pypy/dist/pypy/lib/app_test/test_coroutine.py - copied, changed from r35745, user/stephan/hacks/coroutine/test/test_coroutine.py pypy/dist/pypy/lib/app_test/test_deque_extra.py - copied unchanged from r35791, pypy/dist/pypy/lib/test2/test_deque_extra.py pypy/dist/pypy/lib/app_test/test_exception_extra.py - copied unchanged from r35791, pypy/dist/pypy/lib/test2/test_exception_extra.py pypy/dist/pypy/lib/app_test/test_exceptions_extra.py - copied unchanged from r35791, pypy/dist/pypy/lib/test2/test_exceptions_extra.py pypy/dist/pypy/lib/app_test/test_imp_extra.py - copied unchanged from r35791, pypy/dist/pypy/lib/test2/test_imp_extra.py pypy/dist/pypy/lib/app_test/test_marshal_extra.py - copied unchanged from r35791, pypy/dist/pypy/lib/test2/test_marshal_extra.py pypy/dist/pypy/lib/app_test/test_md5_extra.py - copied unchanged from r35791, pypy/dist/pypy/lib/test2/test_md5_extra.py pypy/dist/pypy/lib/app_test/test_runpy.py - copied unchanged from r35791, pypy/dist/pypy/lib/test2/test_runpy.py pypy/dist/pypy/lib/app_test/test_sha_extra.py - copied unchanged from r35791, pypy/dist/pypy/lib/test2/test_sha_extra.py pypy/dist/pypy/lib/app_test/test_stackless.py - copied, changed from r35791, pypy/dist/pypy/module/_stackless/test/test_stackless.py pypy/dist/pypy/lib/app_test/test_string_extra.py - copied unchanged from r35791, pypy/dist/pypy/lib/test2/test_string_extra.py pypy/dist/pypy/lib/app_test/test_struct_extra.py - copied unchanged from r35791, pypy/dist/pypy/lib/test2/test_struct_extra.py Removed: pypy/dist/pypy/lib/test2/inprogress_test_binascii_extra.py pypy/dist/pypy/lib/test2/no_test_pickle_extra.py pypy/dist/pypy/lib/test2/test_binascii.py pypy/dist/pypy/lib/test2/test_deque_extra.py pypy/dist/pypy/lib/test2/test_exception_extra.py pypy/dist/pypy/lib/test2/test_exceptions_extra.py pypy/dist/pypy/lib/test2/test_imp_extra.py pypy/dist/pypy/lib/test2/test_marshal_extra.py pypy/dist/pypy/lib/test2/test_md5_extra.py pypy/dist/pypy/lib/test2/test_runpy.py pypy/dist/pypy/lib/test2/test_sha_extra.py pypy/dist/pypy/lib/test2/test_string_extra.py pypy/dist/pypy/lib/test2/test_struct_extra.py Modified: pypy/dist/pypy/lib/stackless.py pypy/dist/pypy/lib/stackless_new.py Log: created new 'app_test' directory in pypy/lib and moved all application level tests from 'test2'. moved module/_stackless/test/test_stackless.py into app_test added test_coroutine.py. test_coroutine should run with pypy-c and CPython (with fresh py lib checkout). test_stackless should run with CPython, CStackless and pypy-c. (pypy-c must be compiled with stackless support, of course) Modified: pypy/dist/pypy/lib/stackless.py ============================================================================== --- pypy/dist/pypy/lib/stackless.py (original) +++ pypy/dist/pypy/lib/stackless.py Fri Dec 15 15:59:41 2006 @@ -15,7 +15,10 @@ switches = 0 -from _stackless import coroutine, greenlet +try: + from _stackless import coroutine, greenlet +except ImportError: + from py.magic import coroutine, greenlet __all__ = 'run getcurrent getmain schedule tasklet \ channel TaskletExit coroutine greenlet'.split() Modified: pypy/dist/pypy/lib/stackless_new.py ============================================================================== --- pypy/dist/pypy/lib/stackless_new.py (original) +++ pypy/dist/pypy/lib/stackless_new.py Fri Dec 15 15:59:41 2006 @@ -6,7 +6,10 @@ import traceback import sys -from _stackless import coroutine, greenlet +try: + from _stackless import coroutine, greenlet +except ImportError: + from py.magic import coroutine, greenlet from collections import deque __all__ = 'run getcurrent getmain schedule tasklet channel coroutine \ From auc at codespeak.net Fri Dec 15 16:01:00 2006 From: auc at codespeak.net (auc at codespeak.net) Date: Fri, 15 Dec 2006 16:01:00 +0100 (CET) Subject: [pypy-svn] r35806 - pypy/dist/pypy/translator/goal Message-ID: <20061215150100.CFFD910084@code0.codespeak.net> Author: auc Date: Fri Dec 15 16:00:59 2006 New Revision: 35806 Modified: pypy/dist/pypy/translator/goal/targetlogicstandalone.py Log: back from configuration coma Modified: pypy/dist/pypy/translator/goal/targetlogicstandalone.py ============================================================================== --- pypy/dist/pypy/translator/goal/targetlogicstandalone.py (original) +++ pypy/dist/pypy/translator/goal/targetlogicstandalone.py Fri Dec 15 16:00:59 2006 @@ -7,6 +7,7 @@ opt_defaults = {'translation.stackless' : True, 'translation.debug': True, + 'translation.gc': 'framework', 'objspace.name': 'logic', 'objspace.usemodules._stackless': True} From arigo at codespeak.net Fri Dec 15 16:42:57 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 15 Dec 2006 16:42:57 +0100 (CET) Subject: [pypy-svn] r35808 - in pypy: dist/pypy/doc extradoc/eu-report Message-ID: <20061215154257.82FA01007C@code0.codespeak.net> Author: arigo Date: Fri Dec 15 16:42:55 2006 New Revision: 35808 Added: pypy/extradoc/eu-report/D07.1_Massive_Parallelism_and_Translation_Aspects-2006-12-15.pdf - copied unchanged from r35799, pypy/extradoc/eu-report/D07.1_Massive_Parallelism_and_Translation_Aspects-interim-2006-12-15.pdf Removed: pypy/extradoc/eu-report/D07.1_Massive_Parallelism_and_Translation_Aspects-interim-2006-12-15.pdf Modified: pypy/dist/pypy/doc/index-report.txt pypy/dist/pypy/doc/news.txt Log: Remove the "interim" in the name of the D07 report file. Modified: pypy/dist/pypy/doc/index-report.txt ============================================================================== --- pypy/dist/pypy/doc/index-report.txt (original) +++ pypy/dist/pypy/doc/index-report.txt Fri Dec 15 16:42:55 2006 @@ -67,7 +67,7 @@ .. _`D05.3 Implementation with Translation Aspects`: http://codespeak.net/svn/pypy/extradoc/eu-report/D05.3_Publish_on_implementation_with_translation_aspects.pdf .. _`D05.4 Encapsulating Low Level Aspects`: http://codespeak.net/svn/pypy/extradoc/eu-report/D05.4_Publish_on_encapsulating_low_level_language_aspects.pdf .. _`D14.1 Report about Milestone/Phase 1`: http://codespeak.net/svn/pypy/extradoc/eu-report/D14.1_Report_about_Milestone_Phase_1.pdf -.. _`D07.1 Massive Parallelism and Translation Aspects`: http://codespeak.net/pypy/extradoc/eu-report/D07.1_Massive_Parallelism_and_Translation_Aspects-interim-2006-12-15.pdf +.. _`D07.1 Massive Parallelism and Translation Aspects`: http://codespeak.net/pypy/extradoc/eu-report/D07.1_Massive_Parallelism_and_Translation_Aspects-2006-12-15.pdf .. _`Draft D09.1 Constraint Solving and Semantic Web`: http://codespeak.net/pypy/extradoc/eu-report/D09.1_Constraint_Solving_and_Semantic_Web-interim-2006-07-28.pdf .. _`D14.3 Report about Milestone/Phase 2`: http://codespeak.net/pypy/extradoc/eu-report/D14.3_Report_about_Milestone_Phase_2-final-2006-08-03.pdf .. _`PyPy's approach to virtual machine construction`: http://codespeak.net/svn/pypy/extradoc/talk/dls2006/pypy-vm-construction.pdf Modified: pypy/dist/pypy/doc/news.txt ============================================================================== --- pypy/dist/pypy/doc/news.txt (original) +++ pypy/dist/pypy/doc/news.txt Fri Dec 15 16:42:55 2006 @@ -46,7 +46,7 @@ memory management is finished. You can download it `as pdf`_. .. _`EU report`: index-report.html -.. _`as pdf`: http://codespeak.net/pypy/extradoc/eu-report/D07.1_Massive_Parallelism_and_Translation_Aspects-interim-2006-12-15.pdf +.. _`as pdf`: http://codespeak.net/pypy/extradoc/eu-report/D07.1_Massive_Parallelism_and_Translation_Aspects-2006-12-15.pdf Duesseldorf sprint #2, 30th October - 5th November over From antocuni at codespeak.net Fri Dec 15 16:44:38 2006 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Fri, 15 Dec 2006 16:44:38 +0100 (CET) Subject: [pypy-svn] r35809 - in pypy/dist/pypy: rpython/lltypesystem translator translator/backendopt translator/backendopt/test Message-ID: <20061215154438.9538F1007A@code0.codespeak.net> Author: antocuni Date: Fri Dec 15 16:44:36 2006 New Revision: 35809 Modified: pypy/dist/pypy/rpython/lltypesystem/lloperation.py pypy/dist/pypy/translator/backendopt/canraise.py pypy/dist/pypy/translator/backendopt/inline.py pypy/dist/pypy/translator/backendopt/test/test_inline.py pypy/dist/pypy/translator/simplify.py Log: Some steps in the direction of making inlining to work with ootypesystem. Modified: pypy/dist/pypy/rpython/lltypesystem/lloperation.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/lloperation.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/lloperation.py Fri Dec 15 16:44:36 2006 @@ -402,6 +402,11 @@ # __________ instrumentation _________ 'instrument_count': LLOp(), + + # __________ ootype operations __________ + 'oosetfield': LLOp(), + 'oogetfield': LLOp(), + 'ooupcast': LLOp(), } # __________ operations on PyObjects __________ Modified: pypy/dist/pypy/translator/backendopt/canraise.py ============================================================================== --- pypy/dist/pypy/translator/backendopt/canraise.py (original) +++ pypy/dist/pypy/translator/backendopt/canraise.py Fri Dec 15 16:44:36 2006 @@ -3,11 +3,17 @@ from pypy.rpython.lltypesystem import lltype from pypy.translator.backendopt import graphanalyze +import py +from pypy.tool.ansi_print import ansi_log +log = py.log.Producer("canraise") +py.log.setconsumer("canraise", ansi_log) + class RaiseAnalyzer(graphanalyze.GraphAnalyzer): def operation_is_true(self, op): try: return bool(LL_OPERATIONS[op.opname].canraise) except KeyError: + log.WARNING("Unknown operation: %s" % op.opname) return True def analyze_exceptblock(self, block, seen=None): Modified: pypy/dist/pypy/translator/backendopt/inline.py ============================================================================== --- pypy/dist/pypy/translator/backendopt/inline.py (original) +++ pypy/dist/pypy/translator/backendopt/inline.py Fri Dec 15 16:44:36 2006 @@ -1,6 +1,6 @@ import sys from pypy.translator.simplify import join_blocks, cleanup_graph -from pypy.translator.simplify import get_graph +from pypy.translator.simplify import get_graph, get_funcobj from pypy.translator.unsimplify import copyvar from pypy.objspace.flow.model import Variable, Constant, Block, Link from pypy.objspace.flow.model import SpaceOperation, c_last_exception @@ -21,7 +21,6 @@ class CannotInline(Exception): pass - def collect_called_graphs(graph, translator): graphs_or_something = {} for block in graph.iterblocks(): @@ -46,7 +45,7 @@ for i, op in enumerate(block.operations): if not op.opname == "direct_call": continue - funcobj = op.args[0].value._obj + funcobj = get_funcobj(op.args[0].value) graph = getattr(funcobj, 'graph', None) # accept a function or a graph as 'inline_func' if (graph is calling_what or @@ -173,7 +172,7 @@ self.varmap = {} self._copied_blocks = {} self.op = block.operations[index_operation] - self.graph_to_inline = self.op.args[0].value._obj.graph + self.graph_to_inline = get_funcobj(self.op.args[0].value).graph self.exception_guarded = False if (block.exitswitch == c_last_exception and index_operation == len(block.operations) - 1): @@ -194,7 +193,7 @@ for i, op in enumerate(block.operations): if not op.opname == "direct_call": continue - funcobj = op.args[0].value._obj + funcobj = get_funcobj(op.args[0].value) graph = getattr(funcobj, 'graph', None) # accept a function or a graph as 'inline_func' if (graph is self.inline_func or @@ -275,7 +274,7 @@ linkfrominlined = Link(linkargs, afterblock) linkfrominlined.prevblock = copiedreturnblock copiedreturnblock.exitswitch = None - copiedreturnblock.exits = [linkfrominlined] + copiedreturnblock.exits = [linkfrominlined] ## HERE assert copiedreturnblock.exits[0].target == afterblock def rewire_exceptblock(self, afterblock): @@ -288,8 +287,7 @@ self.rewire_exceptblock_with_guard(afterblock, copiedexceptblock) # generate blocks that do generic matching for cases when the # heuristic did not work -# self.translator.view() - self.generic_exception_matching(afterblock, copiedexceptblock) + self.generic_exception_matching(afterblock, copiedexceptblock) # HERE def rewire_exceptblock_no_guard(self, afterblock, copiedexceptblock): # find all copied links that go to copiedexceptblock @@ -336,7 +334,7 @@ def generic_exception_matching(self, afterblock, copiedexceptblock): #XXXXX don't look: insert blocks that do exception matching - #for the cases where direct matching did not work + #for the cases where direct matching did not work exc_match = Constant( self.translator.rtyper.getexceptiondata().fn_exception_match) exc_match.concretetype = typeOf(exc_match.value) @@ -368,13 +366,14 @@ l.llexitcase = False blocks[-1].exits.insert(0, l) blocks.append(block) + blocks[-1].exits = blocks[-1].exits[:1] blocks[-1].operations = [] blocks[-1].exitswitch = None blocks[-1].exits[0].exitcase = None del blocks[-1].exits[0].llexitcase linkargs = copiedexceptblock.inputargs - copiedexceptblock.closeblock(Link(linkargs, blocks[0])) + copiedexceptblock.closeblock(Link(linkargs, blocks[0])) ## HERE copiedexceptblock.operations += generate_keepalive(linkargs) @@ -540,7 +539,7 @@ for block in parentgraph.iterblocks(): for op in block.operations: if op.opname == "direct_call": - funcobj = op.args[0].value._obj + funcobj = get_funcobj(op.args[0].value) graph = getattr(funcobj, 'graph', None) if graph is not None: if getattr(getattr(funcobj, '_callable', None), @@ -572,7 +571,7 @@ op = ops[i] i -= 1 if op.opname == "direct_call": - funcobj = op.args[0].value._obj + funcobj = get_funcobj(op.args[0].value) graph = getattr(funcobj, 'graph', None) if graph is not None: if getattr(getattr(funcobj, '_callable', None), Modified: pypy/dist/pypy/translator/backendopt/test/test_inline.py ============================================================================== --- pypy/dist/pypy/translator/backendopt/test/test_inline.py (original) +++ pypy/dist/pypy/translator/backendopt/test/test_inline.py Fri Dec 15 16:44:36 2006 @@ -11,10 +11,12 @@ from pypy.translator.backendopt.inline import instrument_inline_candidates from pypy.translator.translator import TranslationContext, graphof from pypy.rpython.llinterp import LLInterpreter +from pypy.rpython.test.tool import LLRtypeMixin, OORtypeMixin from pypy.rlib.rarithmetic import ovfcheck from pypy.translator.test.snippet import is_perfect_number from pypy.conftest import option + def no_missing_concretetype(node): if isinstance(node, Block): for v in node.inputargs: @@ -39,95 +41,6 @@ checkgraph(graph) traverse(no_missing_concretetype, graph) -def translate(func, argtypes): - t = TranslationContext() - t.buildannotator().build_types(func, argtypes) - t.buildrtyper().specialize() - return t - -def check_inline(func, in_func, sig, entry=None, inline_guarded_calls=False): - if entry is None: - entry = in_func - t = translate(entry, sig) - # inline! - sanity_check(t) # also check before inlining (so we don't blame it) - if option.view: - t.view() - raise_analyzer = canraise.RaiseAnalyzer(t) - inliner = Inliner(t, graphof(t, in_func), func, - t.rtyper.lltype_to_classdef_mapping(), - inline_guarded_calls, - raise_analyzer=raise_analyzer) - inliner.inline_all() - if option.view: - t.view() - sanity_check(t) - interp = LLInterpreter(t.rtyper) - def eval_func(args): - return interp.eval_graph(graphof(t, entry), args) - return eval_func - -def check_auto_inlining(func, sig, multiplier=None, call_count_check=False): - t = translate(func, sig) - if option.view: - t.view() - # inline! - sanity_check(t) # also check before inlining (so we don't blame it) - - if multiplier is not None: - multiplier = {'multiplier': multiplier} - else: - multiplier = {} - - call_count_pred = None - if call_count_check: - call_count_pred = lambda lbl: True - instrument_inline_candidates(t.graphs, **multiplier) - - auto_inlining(t, call_count_pred=call_count_pred, **multiplier) - - sanity_check(t) - if option.view: - t.view() - interp = LLInterpreter(t.rtyper) - def eval_func(args): - return interp.eval_graph(graphof(t, func), args) - return eval_func, t - - -def test_inline_simple(): - def f(x, y): - return (g(x, y) + 1) * x - def g(x, y): - if x > 0: - return x * y - else: - return -x * y - eval_func = check_inline(g, f, [int, int]) - result = eval_func([-1, 5]) - assert result == f(-1, 5) - result = eval_func([2, 12]) - assert result == f(2, 12) - -def test_nothing_to_inline(): - def f(): - return 1 - def g(): - return 2 - eval_func = check_inline(g, f, []) - assert eval_func([]) == 1 - -def test_inline_big(): - def f(x): - result = [] - for i in range(1, x+1): - if is_perfect_number(i): - result.append(i) - return result - eval_func = check_inline(is_perfect_number, f, [int]) - result = eval_func([10]) - assert result.length == len(f(10)) - class CustomError1(Exception): def __init__(self): self.data = 123 @@ -136,401 +49,507 @@ def __init__(self): self.data2 = 456 -def test_inline_raising(): - def f(x): - if x == 1: - raise CustomError1 - return x - def g(x): - a = f(x) - if x == 2: - raise CustomError2 - def h(x): - try: - g(x) - except CustomError1: - return 1 - except CustomError2: - return 2 - return x - eval_func = check_inline(f,g, [int], entry=h) - result = eval_func([0]) - assert result == 0 - result = eval_func([1]) - assert result == 1 - result = eval_func([2]) - assert result == 2 - -def test_inline_several_times(): - def f(x): - return (x + 1) * 2 - def g(x): - if x: - a = f(x) + f(x) +class BaseTestInline: + type_system = None + + def _skip_oo(self, reason): + if self.type_system == 'ootype': + py.test.skip("ootypesystem doesn't support %s, yet" % reason) + + def translate(self, func, argtypes): + t = TranslationContext() + t.buildannotator().build_types(func, argtypes) + t.buildrtyper(type_system=self.type_system).specialize() + return t + + def check_inline(self, func, in_func, sig, entry=None, inline_guarded_calls=False): + if entry is None: + entry = in_func + t = self.translate(entry, sig) + # inline! + sanity_check(t) # also check before inlining (so we don't blame it) + if option.view: + t.view() + raise_analyzer = canraise.RaiseAnalyzer(t) + inliner = Inliner(t, graphof(t, in_func), func, + t.rtyper.lltype_to_classdef_mapping(), + inline_guarded_calls, + raise_analyzer=raise_analyzer) + inliner.inline_all() + if option.view: + t.view() + sanity_check(t) + interp = LLInterpreter(t.rtyper) + def eval_func(args): + return interp.eval_graph(graphof(t, entry), args) + return eval_func + + def check_auto_inlining(self, func, sig, multiplier=None, call_count_check=False): + t = self.translate(func, sig) + if option.view: + t.view() + # inline! + sanity_check(t) # also check before inlining (so we don't blame it) + + if multiplier is not None: + multiplier = {'multiplier': multiplier} else: - a = f(x) + 1 - return a + f(x) - eval_func = check_inline(f, g, [int]) - result = eval_func([0]) - assert result == g(0) - result = eval_func([42]) - assert result == g(42) - -def test_inline_exceptions(): - def f(x): - if x == 0: - raise CustomError1 - if x == 1: - raise CustomError2 - def g(x): - try: - f(x) - except CustomError1: - return 2 - except CustomError2: - return x+2 - return 1 - eval_func = check_inline(f, g, [int]) - result = eval_func([0]) - assert result == 2 - result = eval_func([1]) - assert result == 3 - result = eval_func([42]) - assert result == 1 - -def test_inline_const_exceptions(): - valueError = ValueError() - keyError = KeyError() - def f(x): - if x == 0: - raise valueError - if x == 1: - raise keyError - def g(x): - try: - f(x) - except ValueError: - return 2 - except KeyError: - return x+2 - return 1 - eval_func = check_inline(f, g, [int]) - result = eval_func([0]) - assert result == 2 - result = eval_func([1]) - assert result == 3 - result = eval_func([42]) - assert result == 1 - -def test_inline_exception_guarded(): - def h(x): - if x == 1: - raise CustomError1() - elif x == 2: - raise CustomError2() - return 1 - def f(x): - try: - return h(x) - except: - return 87 - def g(x): - try: - return f(x) - except CustomError1: - return 2 - eval_func = check_inline(f, g, [int], inline_guarded_calls=True) - result = eval_func([0]) - assert result == 1 - result = eval_func([1]) - assert result == 87 - result = eval_func([2]) - assert result == 87 - -def test_inline_var_exception(): - def f(x): - e = None - if x == 0: - e = CustomError1() - elif x == 1: - e = KeyError() - if x == 0 or x == 1: - raise e - def g(x): - try: - f(x) - except CustomError1: + multiplier = {} + + call_count_pred = None + if call_count_check: + call_count_pred = lambda lbl: True + instrument_inline_candidates(t.graphs, **multiplier) + + auto_inlining(t, call_count_pred=call_count_pred, **multiplier) + + sanity_check(t) + if option.view: + t.view() + interp = LLInterpreter(t.rtyper) + def eval_func(args): + return interp.eval_graph(graphof(t, func), args) + return eval_func, t + + + def test_inline_simple(self): + def f(x, y): + return (g(x, y) + 1) * x + def g(x, y): + if x > 0: + return x * y + else: + return -x * y + eval_func = self.check_inline(g, f, [int, int]) + result = eval_func([-1, 5]) + assert result == f(-1, 5) + result = eval_func([2, 12]) + assert result == f(2, 12) + + def test_nothing_to_inline(self): + def f(): + return 1 + def g(): return 2 - except KeyError: - return 3 - return 1 - - eval_func, _ = check_auto_inlining(g, [int], multiplier=10) - result = eval_func([0]) - assert result == 2 - result = eval_func([1]) - assert result == 3 - result = eval_func([42]) - assert result == 1 - -def test_inline_nonraising_into_catching(): - def f(x): - return x+1 - def g(x): - try: - return f(x) - except KeyError: - return 42 - eval_func = check_inline(f, g, [int]) - result = eval_func([7654]) - assert result == 7655 - -def DONOTtest_call_call(): - # for reference. Just remove this test if we decide not to support - # catching exceptions while inlining a graph that contains further - # direct_calls. - def e(x): - if x < 0: - raise KeyError - return x+1 - def f(x): - return e(x)+2 - def g(x): - try: - return f(x)+3 - except KeyError: - return -1 - eval_func = check_inline(f, g, [int]) - result = eval_func([100]) - assert result == 106 - result = eval_func(g, [-100]) - assert result == -1 - -def test_for_loop(): - def f(x): - result = 0 - for i in range(0, x): - result += i - return result - t = translate(f, [int]) - sanity_check(t) # also check before inlining (so we don't blame it) - for graph in t.graphs: - if graph.name.startswith('ll_rangenext'): - break - else: - assert 0, "cannot find ll_rangenext_*() function" - simple_inline_function(t, graph, graphof(t, f)) - sanity_check(t) - interp = LLInterpreter(t.rtyper) - result = interp.eval_graph(graphof(t, f), [10]) - assert result == 45 - -def test_inline_constructor(): - class A: - def __init__(self, x, y): - self.bounds = (x, y) - def area(self, height=10): - return height * (self.bounds[1] - self.bounds[0]) - def f(i): - a = A(117, i) - return a.area() - eval_func = check_inline(A.__init__.im_func, f, [int]) - result = eval_func([120]) - assert result == 30 - -def test_cannot_inline_recursive_function(): - def factorial(n): - if n > 1: - return n * factorial(n-1) - else: + eval_func = self.check_inline(g, f, []) + assert eval_func([]) == 1 + + def test_inline_big(self): + def f(x): + result = [] + for i in range(1, x+1): + if is_perfect_number(i): + result.append(i) + return result + eval_func = self.check_inline(is_perfect_number, f, [int]) + result = eval_func([10]) + result = self.ll_to_list(result) + assert len(result) == len(f(10)) + + def test_inline_raising(self): + def f(x): + if x == 1: + raise CustomError1 + return x + def g(x): + a = f(x) + if x == 2: + raise CustomError2 + def h(x): + try: + g(x) + except CustomError1: + return 1 + except CustomError2: + return 2 + return x + eval_func = self.check_inline(f,g, [int], entry=h) + result = eval_func([0]) + assert result == 0 + result = eval_func([1]) + assert result == 1 + result = eval_func([2]) + assert result == 2 + + def test_inline_several_times(self): + def f(x): + return (x + 1) * 2 + def g(x): + if x: + a = f(x) + f(x) + else: + a = f(x) + 1 + return a + f(x) + eval_func = self.check_inline(f, g, [int]) + result = eval_func([0]) + assert result == g(0) + result = eval_func([42]) + assert result == g(42) + + def test_inline_exceptions(self): + def f(x): + if x == 0: + raise CustomError1 + if x == 1: + raise CustomError2 + def g(x): + try: + f(x) + except CustomError1: + return 2 + except CustomError2: + return x+2 + return 1 + eval_func = self.check_inline(f, g, [int]) + result = eval_func([0]) + assert result == 2 + result = eval_func([1]) + assert result == 3 + result = eval_func([42]) + assert result == 1 + + def test_inline_const_exceptions(self): + valueError = ValueError() + keyError = KeyError() + def f(x): + if x == 0: + raise valueError + if x == 1: + raise keyError + def g(x): + try: + f(x) + except ValueError: + return 2 + except KeyError: + return x+2 + return 1 + eval_func = self.check_inline(f, g, [int]) + result = eval_func([0]) + assert result == 2 + result = eval_func([1]) + assert result == 3 + result = eval_func([42]) + assert result == 1 + + def test_inline_exception_guarded(self): + def h(x): + if x == 1: + raise CustomError1() + elif x == 2: + raise CustomError2() return 1 - def f(n): - return factorial(n//2) - py.test.raises(CannotInline, check_inline, factorial, f, [int]) - -def test_auto_inlining_small_call_big(): - def leaf(n): - total = 0 - i = 0 - while i < n: - total += i - if total > 100: - raise OverflowError - i += 1 - return total - def g(n): - return leaf(n) - def f(n): - try: - return g(n) - except OverflowError: - return -1 - eval_func, t = check_auto_inlining(f, [int], multiplier=10) - f_graph = graphof(t, f) - assert len(collect_called_graphs(f_graph, t)) == 0 - - result = eval_func([10]) - assert result == 45 - result = eval_func([15]) - assert result == -1 - -def test_auto_inlining_small_call_big_call_count(): - def leaf(n): - total = 0 - i = 0 - while i < n: - total += i - if total > 100: - raise OverflowError - i += 1 - return total - def g(n): - return leaf(n) - def f(n): - try: - return g(n) - except OverflowError: - return -1 - eval_func, t = check_auto_inlining(f, [int], multiplier=10, - call_count_check=True) - f_graph = graphof(t, f) - assert len(collect_called_graphs(f_graph, t)) == 0 - - result = eval_func([10]) - assert result == 45 - result = eval_func([15]) - assert result == -1 - -def test_inline_exception_catching(): - def f3(): - raise CustomError1 - def f2(): - try: - f3() - except CustomError1: - return True + def f(x): + try: + return h(x) + except: + return 87 + def g(x): + try: + return f(x) + except CustomError1: + return 2 + eval_func = self.check_inline(f, g, [int], inline_guarded_calls=True) + result = eval_func([0]) + assert result == 1 + result = eval_func([1]) + assert result == 87 + result = eval_func([2]) + assert result == 87 + + def test_inline_var_exception(self): + def f(x): + e = None + if x == 0: + e = CustomError1() + elif x == 1: + e = KeyError() + if x == 0 or x == 1: + raise e + def g(x): + try: + f(x) + except CustomError1: + return 2 + except KeyError: + return 3 + return 1 + + eval_func, _ = self.check_auto_inlining(g, [int], multiplier=10) + result = eval_func([0]) + assert result == 2 + result = eval_func([1]) + assert result == 3 + result = eval_func([42]) + assert result == 1 + + def test_inline_nonraising_into_catching(self): + def f(x): + return x+1 + def g(x): + try: + return f(x) + except KeyError: + return 42 + eval_func = self.check_inline(f, g, [int]) + result = eval_func([7654]) + assert result == 7655 + + def DONOTtest_call_call(self): + # for reference. Just remove this test if we decide not to support + # catching exceptions while inlining a graph that contains further + # direct_calls. + def e(x): + if x < 0: + raise KeyError + return x+1 + def f(x): + return e(x)+2 + def g(x): + try: + return f(x)+3 + except KeyError: + return -1 + eval_func = self.check_inline(f, g, [int]) + result = eval_func([100]) + assert result == 106 + result = eval_func(g, [-100]) + assert result == -1 + + def test_for_loop(self): + def f(x): + result = 0 + for i in range(0, x): + result += i + return result + t = self.translate(f, [int]) + sanity_check(t) # also check before inlining (so we don't blame it) + for graph in t.graphs: + if graph.name.startswith('ll_rangenext'): + break else: - return False - def f(): - return f2() - eval_func = check_inline(f2, f, []) - result = eval_func([]) - assert result is True - -def test_inline_catching_different_exception(): - d = {1: 2} - def f2(n): - try: - return ovfcheck(n+1) - except OverflowError: - raise - def f(n): - try: - return f2(n) - except ValueError: - return -1 - eval_func = check_inline(f2, f, [int]) - result = eval_func([54]) - assert result == 55 - -def test_auto_inline_os_path_isdir(): - directory = "./." - def f(): - return os.path.isdir(directory) - eval_func, _ = check_auto_inlining(f, []) - result = eval_func([]) - assert result is True - -def test_inline_raiseonly(): - def f2(x): - raise CustomError1 - def f(x): - try: - return f2(x) - except CustomError1: - return 42 - eval_func = check_inline(f2, f, [int]) - result = eval_func([98371]) - assert result == 42 - -def test_measure_median_execution_cost(): - def f(x): - x += 1 - x += 1 - x += 1 - while True: - x += 1 - x += 1 - x += 1 - if x: break - x += 1 + assert 0, "cannot find ll_rangenext_*() function" + simple_inline_function(t, graph, graphof(t, f)) + sanity_check(t) + interp = LLInterpreter(t.rtyper) + result = interp.eval_graph(graphof(t, f), [10]) + assert result == 45 + + def test_inline_constructor(self): + class A: + def __init__(self, x, y): + self.bounds = (x, y) + def area(self, height=10): + return height * (self.bounds[1] - self.bounds[0]) + def f(i): + a = A(117, i) + return a.area() + eval_func = self.check_inline(A.__init__.im_func, f, [int]) + result = eval_func([120]) + assert result == 30 + + def test_cannot_inline_recursive_function(self): + def factorial(n): + if n > 1: + return n * factorial(n-1) + else: + return 1 + def f(n): + return factorial(n//2) + py.test.raises(CannotInline, self.check_inline, factorial, f, [int]) + + def test_auto_inlining_small_call_big(self): + self._skip_oo('exception rewiring') + def leaf(n): + total = 0 + i = 0 + while i < n: + total += i + if total > 100: + raise OverflowError + i += 1 + return total + def g(n): + return leaf(n) + def f(n): + try: + return g(n) + except OverflowError: + return -1 + eval_func, t = self.check_auto_inlining(f, [int], multiplier=10) + f_graph = graphof(t, f) + assert len(collect_called_graphs(f_graph, t)) == 0 + + result = eval_func([10]) + assert result == 45 + result = eval_func([15]) + assert result == -1 + + def test_auto_inlining_small_call_big_call_count(self): + self._skip_oo('exception rewiring') + def leaf(n): + total = 0 + i = 0 + while i < n: + total += i + if total > 100: + raise OverflowError + i += 1 + return total + def g(n): + return leaf(n) + def f(n): + try: + return g(n) + except OverflowError: + return -1 + eval_func, t = self.check_auto_inlining(f, [int], multiplier=10, + call_count_check=True) + f_graph = graphof(t, f) + assert len(collect_called_graphs(f_graph, t)) == 0 + + result = eval_func([10]) + assert result == 45 + result = eval_func([15]) + assert result == -1 + + def test_inline_exception_catching(self): + def f3(): + raise CustomError1 + def f2(): + try: + f3() + except CustomError1: + return True + else: + return False + def f(): + return f2() + eval_func = self.check_inline(f2, f, []) + result = eval_func([]) + assert result is True + + def test_inline_catching_different_exception(self): + d = {1: 2} + def f2(n): + try: + return ovfcheck(n+1) + except OverflowError: + raise + def f(n): + try: + return f2(n) + except ValueError: + return -1 + eval_func = self.check_inline(f2, f, [int]) + result = eval_func([54]) + assert result == 55 + + def test_auto_inline_os_path_isdir(self): + directory = "./." + def f(): + return os.path.isdir(directory) + eval_func, _ = self.check_auto_inlining(f, []) + result = eval_func([]) + assert result is True + + def test_inline_raiseonly(self): + def f2(x): + raise CustomError1 + def f(x): + try: + return f2(x) + except CustomError1: + return 42 + eval_func = self.check_inline(f2, f, [int]) + result = eval_func([98371]) + assert result == 42 + + def test_measure_median_execution_cost(self): + def f(x): x += 1 x += 1 x += 1 + while True: + x += 1 + x += 1 + x += 1 + if x: break + x += 1 + x += 1 + x += 1 + x += 1 + x += 1 x += 1 - x += 1 - return x - t = TranslationContext() - graph = t.buildflowgraph(f) - res = measure_median_execution_cost(graph) - assert round(res, 5) == round(32.333333333, 5) - -def test_indirect_call_with_exception(): - class Dummy: - pass - def x1(): - return Dummy() # can raise MemoryError - def x2(): - return 2 - def x3(x): - if x: - f = x1 - else: - f = x2 - return f() - def x4(): - try: - x3(0) - x3(1) - except CustomError2: - return 0 - return 1 - assert x4() == 1 - py.test.raises(CannotInline, check_inline, x3, x4, []) - -def test_keepalive_hard_case(): - from pypy.rpython.lltypesystem import lltype - Y = lltype.Struct('y', ('n', lltype.Signed)) - X = lltype.GcStruct('x', ('y', Y)) - def g(x): - if x: - return 3 - else: - return 4 - def f(): - x = lltype.malloc(X) - x.y.n = 2 - y = x.y - z1 = g(y.n) - z = y.n - return z+z1 - eval_func = check_inline(g, f, []) - res = eval_func([]) - assert res == 5 - -def test_correct_keepalive_placement(): - def h(x): - if not x: - raise ValueError - return 1 - def f(x): - s = "a %s" % (x, ) - try: - h(len(s)) - except ValueError: + return x + t = TranslationContext() + graph = t.buildflowgraph(f) + res = measure_median_execution_cost(graph) + assert round(res, 5) == round(32.333333333, 5) + + def test_indirect_call_with_exception(self): + self._skip_oo('exception rewiring') + class Dummy: pass - return -42 - eval_func, t = check_auto_inlining(f, [int]) - res = eval_func([42]) - assert res == -42 + def x1(): + return Dummy() # can raise MemoryError + def x2(): + return 2 + def x3(x): + if x: + f = x1 + else: + f = x2 + return f() + def x4(): + try: + x3(0) + x3(1) + except CustomError2: + return 0 + return 1 + assert x4() == 1 + py.test.raises(CannotInline, self.check_inline, x3, x4, []) + + def test_keepalive_hard_case(self): + from pypy.rpython.lltypesystem import lltype + Y = lltype.Struct('y', ('n', lltype.Signed)) + X = lltype.GcStruct('x', ('y', Y)) + def g(x): + if x: + return 3 + else: + return 4 + def f(): + x = lltype.malloc(X) + x.y.n = 2 + y = x.y + z1 = g(y.n) + z = y.n + return z+z1 + eval_func = self.check_inline(g, f, []) + res = eval_func([]) + assert res == 5 + + def test_correct_keepalive_placement(self): + def h(x): + if not x: + raise ValueError + return 1 + def f(x): + s = "a %s" % (x, ) + try: + h(len(s)) + except ValueError: + pass + return -42 + eval_func, t = self.check_auto_inlining(f, [int]) + res = eval_func([42]) + assert res == -42 + + +class TestInlineLLType(LLRtypeMixin, BaseTestInline): + pass +class TestInlineOOType(OORtypeMixin, BaseTestInline): + pass Modified: pypy/dist/pypy/translator/simplify.py ============================================================================== --- pypy/dist/pypy/translator/simplify.py (original) +++ pypy/dist/pypy/translator/simplify.py Fri Dec 15 16:44:36 2006 @@ -12,27 +12,39 @@ from pypy.objspace.flow.model import checkgraph, traverse, mkentrymap from pypy.rpython.lltypesystem import lloperation +def get_funcobj(func): + """ + Return an object which is supposed to have attributes such as graph and _callable + """ + if hasattr(func, '_obj'): + return func._obj # lltypesystem + else: + return func # ootypesystem + + def get_graph(arg, translator): from pypy.translator.translator import graphof if isinstance(arg, Variable): return None f = arg.value from pypy.rpython.lltypesystem import lltype - if not isinstance(f, lltype._ptr): + from pypy.rpython.ootypesystem import ootype + if not isinstance(f, lltype._ptr) and not isinstance(f, ootype._callable): return None + funcobj = get_funcobj(f) try: - callable = f._obj._callable + callable = funcobj._callable # external function calls don't have a real graph if getattr(callable, "suggested_primitive", False): return None except (AttributeError, KeyError, AssertionError): return None try: - return f._obj.graph + return funcobj.graph except AttributeError: return None try: - callable = f._obj._callable + callable = funcobj._callable return graphof(translator, callable) except (AttributeError, KeyError, AssertionError): return None From ac at codespeak.net Fri Dec 15 17:00:50 2006 From: ac at codespeak.net (ac at codespeak.net) Date: Fri, 15 Dec 2006 17:00:50 +0100 (CET) Subject: [pypy-svn] r35810 - in pypy/dist/pypy/jit: codegen codegen/i386 codegen/i386/test timeshifter Message-ID: <20061215160050.99F1510084@code0.codespeak.net> Author: ac Date: Fri Dec 15 17:00:49 2006 New Revision: 35810 Modified: pypy/dist/pypy/jit/codegen/i386/rgenop.py pypy/dist/pypy/jit/codegen/i386/test/test_genc_portal.py pypy/dist/pypy/jit/codegen/model.py pypy/dist/pypy/jit/timeshifter/rtimeshift.py Log: Pause builders when they are put on return/split/global_merge chains so they can release temporary resources (The i386 one will release it's MachineCodeBlock). This way we won't use up the addresspace so easily. 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 Dec 15 17:00:49 2006 @@ -220,27 +220,51 @@ class Builder(GenBuilder): - def __init__(self, rgenop, mc_factory, stackdepth): + def __init__(self, rgenop, stackdepth): self.rgenop = rgenop self.stackdepth = stackdepth self.mc = None - self._mc_factory = mc_factory self._pending_come_from = {} self.start = 0 + self.closed = False + self.tail = (0, 0) rgenop.openbuilders += 1 #os.write(1, 'Open builders+: %d\n' % rgenop.openbuilders) def _open(self): - if self.mc is None and self._pending_come_from is not None: - self.mc = self._mc_factory() - self.start = self.mc.tell() - come_froms = self._pending_come_from - self._pending_come_from = None - for start, (end, insn) in come_froms.iteritems(): - mc = self.rgenop.InMemoryCodeBuilder(start, end) - self._emit_come_from(mc, insn, self.start) + if self.mc is None and not self.closed: + self.mc = self.rgenop.open_mc() + if not self.start: + # This is the first open. remember the start address + # and patch all come froms. + self.start = self.mc.tell() + come_froms = self._pending_come_from + self._pending_come_from = None + for start, (end, insn) in come_froms.iteritems(): + mc = self.rgenop.InMemoryCodeBuilder(start, end) + self._emit_come_from(mc, insn, self.start) + mc.done() + else: + # We have been paused and are being opened again. + # Patch the jump at the end of the previous codeblock. + mc = self.rgenop.InMemoryCodeBuilder(*self.tail) + mc.JMP(rel32(self.mc.tell())) mc.done() + def pause(self): + if self.mc is None: + return + start = self.mc.tell() + self.mc.JMP(rel32(0)) + end = self.mc.tell() + self.tail = (start, end) + self.mc.done() + self.rgenop.close_mc(self.mc) + self.mc = None + + def resume(self): + self._open() + def _emit_come_from(self, mc, insn, addr): if insn == 'JMP': mc.JMP(rel32(addr)) @@ -273,6 +297,7 @@ return [Var(pos) for pos in range(numargs-1, -1, -1)] def _close(self): + self.closed = True self.mc.done() self.rgenop.close_mc(self.mc) self.mc = None @@ -459,6 +484,7 @@ return targetbuilder def finish_and_return(self, sigtoken, gv_returnvar): + self._open() numargs = sigtoken # for now initialstackdepth = numargs + 1 self.mc.MOV(eax, gv_returnvar.operand(self)) @@ -467,6 +493,7 @@ self._close() def finish_and_goto(self, outputargs_gv, target): + self._open() remap_stack_layout(self, outputargs_gv, target) self.mc.JMP(rel32(target.startaddr)) self._close() @@ -961,7 +988,7 @@ assert len(self.mcs) == self.total_code_blocks def openbuilder(self, stackdepth): - return Builder(self, self.open_mc, stackdepth) + return Builder(self, stackdepth) def newgraph(self, sigtoken, name): numargs = sigtoken # for now Modified: pypy/dist/pypy/jit/codegen/i386/test/test_genc_portal.py ============================================================================== --- pypy/dist/pypy/jit/codegen/i386/test/test_genc_portal.py (original) +++ pypy/dist/pypy/jit/codegen/i386/test/test_genc_portal.py Fri Dec 15 17:00:49 2006 @@ -59,9 +59,6 @@ backendoptimize=backendoptimize) cmdargs = ' '.join([str(arg) for arg in main_args]) output = self.cbuilder.cmdexec(cmdargs) - print '-'*60 - print output - print '-'*60 lines = output.split() lastline = lines[-1] assert not lastline.startswith('EXCEPTION:') Modified: pypy/dist/pypy/jit/codegen/model.py ============================================================================== --- pypy/dist/pypy/jit/codegen/model.py (original) +++ pypy/dist/pypy/jit/codegen/model.py Fri Dec 15 17:00:49 2006 @@ -142,7 +142,15 @@ '''Optional method: prints or logs the position of the generated code along with the given msg. ''' - + def pause(self): + '''Optional method: Called when the builder will not be used for a + while. This allows the builder to free temporary resources needed + during code generation. The next call to the builder will have to be + to enter_next_block, finish_and_got, finish_and_return or resume. + ''' + def resume(self): + 'Resumes a paused builder.' + class GenLabel(object): '''A "smart" label. Represents an address of the start of a basic block and the location of the inputargs on entry to that block.''' Modified: pypy/dist/pypy/jit/timeshifter/rtimeshift.py ============================================================================== --- pypy/dist/pypy/jit/timeshifter/rtimeshift.py (original) +++ pypy/dist/pypy/jit/timeshifter/rtimeshift.py Fri Dec 15 17:00:49 2006 @@ -308,6 +308,7 @@ resuming.mergesleft -= 1 def guard_global_merge(jitstate, resumepoint): + jitstate.curbuilder.pause() dispatchqueue = jitstate.frame.dispatchqueue jitstate.next = dispatchqueue.global_merge_chain dispatchqueue.global_merge_chain = jitstate @@ -392,6 +393,7 @@ elif dispatchqueue.global_merge_chain is not None: jitstate = dispatchqueue.global_merge_chain dispatchqueue.global_merge_chain = jitstate.next + jitstate.curbuilder.resume() return jitstate else: oldjitstate.resumepoint = -1 @@ -439,6 +441,7 @@ def save_return(jitstate): # add 'jitstate' to the chain of return-jitstates + jitstate.curbuilder.pause() dispatchqueue = jitstate.frame.dispatchqueue jitstate.next = dispatchqueue.return_chain dispatchqueue.return_chain = jitstate @@ -913,10 +916,13 @@ while return_chain is not None: jitstate = return_chain return_chain = return_chain.next + jitstate.curbuilder.resume() res = retrieve_jitstate_for_merge(return_cache, jitstate, (), return_marker, force_merge=force_merge) if res is False: # not finished + if still_pending: + still_pending.curbuilder.pause() jitstate.next = still_pending still_pending = jitstate @@ -929,10 +935,13 @@ while return_chain is not None: jitstate = return_chain return_chain = return_chain.next + jitstate.curbuilder.resume() res = retrieve_jitstate_for_merge(return_cache, jitstate, (), return_marker, force_merge=force_merge) if res is False: # not finished + if still_pending: + still_pending.curbuilder.pause() jitstate.next = still_pending still_pending = jitstate return still_pending @@ -992,4 +1001,3 @@ leave_frame(jitstate) jitstate = jitstate.next return return_chain # a jitstate, which is the head of the chain - From pedronis at codespeak.net Fri Dec 15 17:05:48 2006 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Fri, 15 Dec 2006 17:05:48 +0100 (CET) Subject: [pypy-svn] r35811 - pypy/dist/pypy/doc Message-ID: <20061215160548.9C58610084@code0.codespeak.net> Author: pedronis Date: Fri Dec 15 17:05:45 2006 New Revision: 35811 Modified: pypy/dist/pypy/doc/eventhistory.txt pypy/dist/pypy/doc/news.txt Log: move some past news into eventhistory. Modified: pypy/dist/pypy/doc/eventhistory.txt ============================================================================== --- pypy/dist/pypy/doc/eventhistory.txt (original) +++ pypy/dist/pypy/doc/eventhistory.txt Fri Dec 15 17:05:45 2006 @@ -7,6 +7,27 @@ .. _news: news.html +EuroPython PyPy sprint 6-9 July 2006 +================================================================== + +Once again a PyPy sprint took place right after the EuroPython +Conference from the *6th to the 9th of July*. + +Read more in the `EuroPython 2006 sprint report`_. + +.. _`EuroPython 2006 sprint report`: http://codespeak.net/pypy/extradoc/sprintinfo/post-ep2006/report.txt + +PyPy at XP 2006 and Agile 2006 +================================================================== + +PyPy presented experience reports at the two main agile conferences +this year, `XP 2006`_ and `Agile 2006`_. +Both experience reports focus on aspects of the sprint-driven +development method that is being used in PyPy. + +.. _`XP 2006`: http://virtual.vtt.fi/virtual/xp2006/ +.. _`Agile 2006`: http://www.agile2006.org/ + Duesseldorf PyPy sprint 2-9 June 2006 ================================================================== Modified: pypy/dist/pypy/doc/news.txt ============================================================================== --- pypy/dist/pypy/doc/news.txt (original) +++ pypy/dist/pypy/doc/news.txt Fri Dec 15 17:05:45 2006 @@ -124,30 +124,6 @@ the `release announcement `__ to read about the many new features in this release. -EuroPython PyPy sprint 6-9 July 2006 -================================================================== - -Once again a PyPy sprint will take place right after the EuroPython -Conference. This year it will be from the *6th to the 9th of July*. - -Read more in `EuroPython sprint announcement`_, see who is planning to attend -on `the people page`_. There is also a page_ in the python wiki. - -.. _`EuroPython sprint announcement`: http://codespeak.net/pypy/extradoc/sprintinfo/post-ep2006/announce.html -.. _`the people page`: http://codespeak.net/pypy/extradoc/sprintinfo/post-ep2006/people.html -.. _page: http://wiki.python.org/moin/EuroPython2006 - -PyPy at XP 2006 and Agile 2006 -================================================================== - -PyPy will present experience reports at the two main agile conferences -this year, `XP 2006`_ and `Agile 2006`_. -Both experience reports focus on aspects of the sprint-driven -development method that is being used in PyPy. - -.. _`XP 2006`: http://virtual.vtt.fi/virtual/xp2006/ -.. _`Agile 2006`: http://www.agile2006.org/ - PyPy and Summer of Code 2006 ================================================================== From ac at codespeak.net Fri Dec 15 17:44:35 2006 From: ac at codespeak.net (ac at codespeak.net) Date: Fri, 15 Dec 2006 17:44:35 +0100 (CET) Subject: [pypy-svn] r35814 - pypy/dist/pypy/jit/codegen/i386 Message-ID: <20061215164435.1457910084@code0.codespeak.net> Author: ac Date: Fri Dec 15 17:44:35 2006 New Revision: 35814 Modified: pypy/dist/pypy/jit/codegen/i386/rgenop.py Log: Remove some debug prints. 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 Dec 15 17:44:35 2006 @@ -228,8 +228,6 @@ self.start = 0 self.closed = False self.tail = (0, 0) - rgenop.openbuilders += 1 - #os.write(1, 'Open builders+: %d\n' % rgenop.openbuilders) def _open(self): if self.mc is None and not self.closed: @@ -301,8 +299,6 @@ self.mc.done() self.rgenop.close_mc(self.mc) self.mc = None - self.rgenop.openbuilders -= 1 - #os.write(1, 'Open builders-: %d\n' % self.rgenop.openbuilders) def _fork(self): return self.rgenop.openbuilder(self.stackdepth) @@ -961,7 +957,6 @@ from pypy.jit.codegen.i386.codebuf import InMemoryCodeBuilder MC_SIZE = 65536 - openbuilders = 0 def __init__(self): self.mcs = [] # machine code blocks where no-one is currently writing @@ -975,7 +970,6 @@ else: # XXX supposed infinite for now self.total_code_blocks += 1 - #os.write(1, 'Open codeblocks: %d\n' % (self.total_code_blocks,)) return self.MachineCodeBlock(self.MC_SIZE) def close_mc(self, mc): From pedronis at codespeak.net Fri Dec 15 17:46:48 2006 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Fri, 15 Dec 2006 17:46:48 +0100 (CET) Subject: [pypy-svn] r35815 - pypy/dist/pypy/jit Message-ID: <20061215164648.4EF9D10083@code0.codespeak.net> Author: pedronis Date: Fri Dec 15 17:46:47 2006 New Revision: 35815 Modified: pypy/dist/pypy/jit/TODO.txt Log: update TODO Modified: pypy/dist/pypy/jit/TODO.txt ============================================================================== --- pypy/dist/pypy/jit/TODO.txt (original) +++ pypy/dist/pypy/jit/TODO.txt Fri Dec 15 17:46:47 2006 @@ -13,9 +13,6 @@ beginning of the portal, but concretely implemented in the portal entry -- minimize the number of concurrently open machinecodeblocks in the - machine code backends - - make backend opts usable on the interp+timeshifted interp graph forest Improvements @@ -29,7 +26,8 @@ - floats -- improve backends (reg. allocation ...) +- improve backends (reg. allocation, produce code more lazily in larger units and avoid for example + many open machine blocks at the same time without resorting to many jumps...) - jit-friendlier interpreter (whatever, as needed) From stephan at codespeak.net Fri Dec 15 18:12:52 2006 From: stephan at codespeak.net (stephan at codespeak.net) Date: Fri, 15 Dec 2006 18:12:52 +0100 (CET) Subject: [pypy-svn] r35817 - in pypy/dist/pypy/lib: . app_test Message-ID: <20061215171252.040501007B@code0.codespeak.net> Author: stephan Date: Fri Dec 15 18:12:51 2006 New Revision: 35817 Modified: pypy/dist/pypy/lib/app_test/test_stackless.py pypy/dist/pypy/lib/stackless.py pypy/dist/pypy/lib/stackless_new.py Log: removed the references to py.magic.coroutine. Instead, http://codespeak.net/svn/user/stephan/hacks/coroutine/ must in the python path in order to run the test_coroutine and test_stackless tests from CPython. test_stackless is actually testing stackless_new. Modified: pypy/dist/pypy/lib/app_test/test_stackless.py ============================================================================== --- pypy/dist/pypy/lib/app_test/test_stackless.py (original) +++ pypy/dist/pypy/lib/app_test/test_stackless.py Fri Dec 15 18:12:51 2006 @@ -11,6 +11,7 @@ withinit = False except ImportError: from pypy.lib import stackless_new as stackless + #from pypy.lib import stackless withinit = True from py.test import skip Modified: pypy/dist/pypy/lib/stackless.py ============================================================================== --- pypy/dist/pypy/lib/stackless.py (original) +++ pypy/dist/pypy/lib/stackless.py Fri Dec 15 18:12:51 2006 @@ -17,8 +17,13 @@ try: from _stackless import coroutine, greenlet -except ImportError: - from py.magic import coroutine, greenlet +except ImportError: # we are running from CPython + # you must have coroutine from + # http://codespeak.net/svn/user/stephan/hacks/coroutine/ + # in your path in order to get the following to work + + from py.magic import greenlet + from coroutine import coroutine __all__ = 'run getcurrent getmain schedule tasklet \ channel TaskletExit coroutine greenlet'.split() @@ -879,3 +884,5 @@ __init() +_init = __init # compatibility to stackless_new + Modified: pypy/dist/pypy/lib/stackless_new.py ============================================================================== --- pypy/dist/pypy/lib/stackless_new.py (original) +++ pypy/dist/pypy/lib/stackless_new.py Fri Dec 15 18:12:51 2006 @@ -8,8 +8,14 @@ import sys try: from _stackless import coroutine, greenlet -except ImportError: - from py.magic import coroutine, greenlet +except ImportError: # we are running from CPython + # you must have coroutine from + # http://codespeak.net/svn/user/stephan/hacks/coroutine/ + # in your path in order to get the following to work + + from py.magic import greenlet + from coroutine import coroutine + from collections import deque __all__ = 'run getcurrent getmain schedule tasklet channel coroutine \ From pedronis at codespeak.net Fri Dec 15 18:34:59 2006 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Fri, 15 Dec 2006 18:34:59 +0100 (CET) Subject: [pypy-svn] r35818 - pypy/dist/pypy/doc Message-ID: <20061215173459.CD5331007C@code0.codespeak.net> Author: pedronis Date: Fri Dec 15 18:34:58 2006 New Revision: 35818 Modified: pypy/dist/pypy/doc/draft-jit-outline.txt Log: describe in words the timeshifting of the small example Modified: pypy/dist/pypy/doc/draft-jit-outline.txt ============================================================================== --- pypy/dist/pypy/doc/draft-jit-outline.txt (original) +++ pypy/dist/pypy/doc/draft-jit-outline.txt Fri Dec 15 18:34:58 2006 @@ -392,8 +392,8 @@ -------------------------- The basic idea of timeshifting is to transform operations depending on -the color of their operands. Variables themselves need to be represented -based on their color: +the color of their operands and result. Variables themselves need to +be represented based on their color: * The green variables are the compile-time variables. Their values are meant to be available during compile-time already. A variable that @@ -451,6 +451,29 @@ structure at compile-time - this decision is based on the static `Deep freezing`_ analysis performed by the hint-annotator. +The Example again +------------------- + +If we timeshift the `ll_plus_minus`__ example, given the described +binding time assignments, the only red operations generating +code in the output residual graph are ``acc += x``, ``acc -= +x``. Timeshifting substitute them with helpers that do emit such +operations. + +All the rest involves green variables and is left unmutated by +timeshifting. The corresponding computations, the loop over the +"instructions" and dispaching on them would happen at compile-time. + +The timeshifted version of ll_plus_minus for the input "+-+" would +produce something like (in pseudo notation):: + + residual_plus_minus_graph(x,y): + v0 = int_add(x , y) + v1 = int_sub(v0, y) + v2 = int_add(v1, y) + return v2 + +__ `Example above`_ Support code -------------- From pedronis at codespeak.net Fri Dec 15 19:05:17 2006 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Fri, 15 Dec 2006 19:05:17 +0100 (CET) Subject: [pypy-svn] r35819 - pypy/dist/pypy/doc Message-ID: <20061215180517.1B5821007B@code0.codespeak.net> Author: pedronis Date: Fri Dec 15 19:05:10 2006 New Revision: 35819 Modified: pypy/dist/pypy/doc/draft-jit-outline.txt Log: terminological consistency Modified: pypy/dist/pypy/doc/draft-jit-outline.txt ============================================================================== --- pypy/dist/pypy/doc/draft-jit-outline.txt (original) +++ pypy/dist/pypy/doc/draft-jit-outline.txt Fri Dec 15 19:05:10 2006 @@ -456,7 +456,7 @@ If we timeshift the `ll_plus_minus`__ example, given the described binding time assignments, the only red operations generating -code in the output residual graph are ``acc += x``, ``acc -= +code in the output residual code are ``acc += x``, ``acc -= x``. Timeshifting substitute them with helpers that do emit such operations. @@ -467,7 +467,7 @@ The timeshifted version of ll_plus_minus for the input "+-+" would produce something like (in pseudo notation):: - residual_plus_minus_graph(x,y): + residual_plus_minus(x,y): v0 = int_add(x , y) v1 = int_sub(v0, y) v2 = int_add(v1, y) From arigo at codespeak.net Fri Dec 15 19:39:20 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 15 Dec 2006 19:39:20 +0100 (CET) Subject: [pypy-svn] r35820 - pypy/dist/pypy/doc Message-ID: <20061215183920.CF01C1007B@code0.codespeak.net> Author: arigo Date: Fri Dec 15 19:39:17 2006 New Revision: 35820 Modified: pypy/dist/pypy/doc/draft-jit-outline.txt Log: Merges and splits. Modified: pypy/dist/pypy/doc/draft-jit-outline.txt ============================================================================== --- pypy/dist/pypy/doc/draft-jit-outline.txt (original) +++ pypy/dist/pypy/doc/draft-jit-outline.txt Fri Dec 15 19:39:17 2006 @@ -552,10 +552,53 @@ become calls to helpers. -Split and Merges +Merges and Splits -------------------- -... +The description of the timeshifting transformation given so far misses a +critical aspect: how to handle control flow (e.g. loops) that involves +red variables. It is easy to see why the timeshifted graphs cannot have +exactly the same control flow than the original graphs: we may not know +at compile-time how many iterations a loop will do at run-time, nor what +branches of a condition will be taken. + +The issue of loops is handled by *merge points*. Merge points are +special operations inserted just after join points, i.e. just after two +or more incoming control flow paths meet. A merge point is a check to +see if the compiler, i.e. the timeshifted graph, has come back to a +state that was previously seen at the same merge point. The goal is +that when the timeshifted graph loops back, the residual code that its +red operations produces should loop as well, as soon as possible. +Without the merge point logic, the timeshifted graph would simply go on +looping forever, producing an infinitely long sequence of residual +operations. The merge point prevents that: when a state is encountered +that was already seen before, the merge logic emits in the residual code +a jump that goes back to the residual code corresponding to the older +state, thus creating a residual loop. After this, the timeshifted graph +stops executing. + +The mirror issue is that of *split points*. Splits are conditional +branches. There are two kinds of splits: the ones whose condition is +itself a green variable, and the ones whose condition is red. A green +split (i.e. the former) is left untouched by the timeshifting +transformation: as the condition will be known a compile-time, we know +at compile-time which of the branches is followed. + +A red split is more delicate. It must generate in a conditional branch +in the residual code. From a theoretical point of view, this is done by +emitting a conditional jump instruction, and then *forking* the +compile-time process in two identical copies: each copy follows one of +the branches in the timeshifted graph, and goes on generating code in +the corresponding branch in the residual code. + +In practice, this is implemented by making a copy of the current JIT +state, which is added to a scheduler's queue. At the end of the +timeshifted graph, an extra call to the scheduler will fetch the next +pending JIT state and jump back to it. (This implies that the control +flow of the timeshifted graph is mangled by the timeshifting +transformation, to allow the last block of the graph to jump back to any +of the red splits.) + Calls and inlining --------------------- From pedronis at codespeak.net Fri Dec 15 19:45:22 2006 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Fri, 15 Dec 2006 19:45:22 +0100 (CET) Subject: [pypy-svn] r35821 - pypy/dist/pypy/doc Message-ID: <20061215184522.9D0131007B@code0.codespeak.net> Author: pedronis Date: Fri Dec 15 19:45:21 2006 New Revision: 35821 Modified: pypy/dist/pypy/doc/draft-jit-outline.txt Log: small fixes. Modified: pypy/dist/pypy/doc/draft-jit-outline.txt ============================================================================== --- pypy/dist/pypy/doc/draft-jit-outline.txt (original) +++ pypy/dist/pypy/doc/draft-jit-outline.txt Fri Dec 15 19:45:21 2006 @@ -579,12 +579,12 @@ The mirror issue is that of *split points*. Splits are conditional branches. There are two kinds of splits: the ones whose condition is -itself a green variable, and the ones whose condition is red. A green +itself on a green variable, and the ones whose condition is red. A green split (i.e. the former) is left untouched by the timeshifting transformation: as the condition will be known a compile-time, we know -at compile-time which of the branches is followed. +at compile-time which of the branches has to be followed. -A red split is more delicate. It must generate in a conditional branch +A red split is more delicate. It must generate a conditional branch in the residual code. From a theoretical point of view, this is done by emitting a conditional jump instruction, and then *forking* the compile-time process in two identical copies: each copy follows one of From arigo at codespeak.net Sat Dec 16 10:56:35 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 16 Dec 2006 10:56:35 +0100 (CET) Subject: [pypy-svn] r35827 - pypy/dist/pypy/lib/app_test Message-ID: <20061216095635.E9F661007B@code0.codespeak.net> Author: arigo Date: Sat Dec 16 10:56:32 2006 New Revision: 35827 Modified: pypy/dist/pypy/lib/app_test/test_coroutine.py Log: Add tests for the strange "is_zombie" property. Modified: pypy/dist/pypy/lib/app_test/test_coroutine.py ============================================================================== --- pypy/dist/pypy/lib/app_test/test_coroutine.py (original) +++ pypy/dist/pypy/lib/app_test/test_coroutine.py Sat Dec 16 10:56:32 2006 @@ -8,8 +8,31 @@ co = coroutine() def f(): print 'in coro' + assert not co.is_zombie co.bind(f) assert not co.is_zombie + co.switch() + assert not co.is_zombie + + def test_is_zombie_del(self): + import gc + res = [] + class MyCoroutine(coroutine): + def __del__(self): + res.append(self.is_zombie) + def f(): + print 'in coro' + co = MyCoroutine() + co.bind(f) + co.switch() + del co + for i in range(5): + gc.collect() + if res: + break + if not res: + skip("MyCoroutine object not garbage-collected yet?") + assert res[0], "is_zombie was False in __del__" def test_raise_propagate(self): co = coroutine() @@ -46,6 +69,7 @@ co = coroutine() def f(): pass + assert not co.is_alive co.bind(f) assert co.is_alive co.kill() From arigo at codespeak.net Sat Dec 16 10:58:09 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 16 Dec 2006 10:58:09 +0100 (CET) Subject: [pypy-svn] r35828 - in pypy/dist/pypy/lib: app_test pyontology Message-ID: <20061216095809.6700D1007B@code0.codespeak.net> Author: arigo Date: Sat Dec 16 10:58:08 2006 New Revision: 35828 Modified: pypy/dist/pypy/lib/app_test/ (props changed) pypy/dist/pypy/lib/pyontology/autopath.py (props changed) Log: fixeol From arigo at codespeak.net Sat Dec 16 11:00:06 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 16 Dec 2006 11:00:06 +0100 (CET) Subject: [pypy-svn] r35829 - pypy/dist/pypy/lib/app_test Message-ID: <20061216100006.772651007B@code0.codespeak.net> Author: arigo Date: Sat Dec 16 11:00:04 2006 New Revision: 35829 Modified: pypy/dist/pypy/lib/app_test/test_coroutine.py pypy/dist/pypy/lib/app_test/test_stackless.py Log: Skip instead of crash if coroutine.py is not importable. Modified: pypy/dist/pypy/lib/app_test/test_coroutine.py ============================================================================== --- pypy/dist/pypy/lib/app_test/test_coroutine.py (original) +++ pypy/dist/pypy/lib/app_test/test_coroutine.py Sat Dec 16 11:00:04 2006 @@ -1,7 +1,11 @@ -from pypy.lib.stackless import coroutine - from py.test import skip, raises +try: + from pypy.lib.stackless import coroutine +except ImportError, e: + skip('cannot import stackless: %s' % (e,)) + + class Test_Coroutine: def test_is_zombie(self): Modified: pypy/dist/pypy/lib/app_test/test_stackless.py ============================================================================== --- pypy/dist/pypy/lib/app_test/test_stackless.py (original) +++ pypy/dist/pypy/lib/app_test/test_stackless.py Sat Dec 16 11:00:04 2006 @@ -4,16 +4,19 @@ 2. CPython (with the stackless_new module in the path 3. pypy-c """ +from py.test import skip try: import stackless if 'coroutine' in dir(stackless): raise ImportError("We are running pypy-c") withinit = False except ImportError: - from pypy.lib import stackless_new as stackless + try: + from pypy.lib import stackless_new as stackless + except ImportError, e: + skip('cannot import stackless: %s' % (e,)) #from pypy.lib import stackless withinit = True -from py.test import skip class Test_Stackless: From arigo at codespeak.net Sat Dec 16 11:29:31 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 16 Dec 2006 11:29:31 +0100 (CET) Subject: [pypy-svn] r35830 - in pypy/dist/pypy/rpython: . lltypesystem lltypesystem/test ootypesystem Message-ID: <20061216102931.01FDC1007F@code0.codespeak.net> Author: arigo Date: Sat Dec 16 11:29:25 2006 New Revision: 35830 Added: pypy/dist/pypy/rpython/ootypesystem/ooopimpl.py (contents, props changed) Modified: pypy/dist/pypy/rpython/llinterp.py pypy/dist/pypy/rpython/lltypesystem/lloperation.py pypy/dist/pypy/rpython/lltypesystem/test/test_lloperation.py Log: * Trying (slightly) harder to point out that changes in lloperation should be followed by a run in test_lloperation :-) * Finish adding all oo operations to the table, and put the canfold ones in a new ooopimpl mirrorring lltype's opimpl.py. Modified: pypy/dist/pypy/rpython/llinterp.py ============================================================================== --- pypy/dist/pypy/rpython/llinterp.py (original) +++ pypy/dist/pypy/rpython/llinterp.py Sat Dec 16 11:29:25 2006 @@ -223,8 +223,7 @@ ophandler = getattr(self, 'op_' + opname, None) if ophandler is None: # try to import the operation from opimpl.py - from pypy.rpython.lltypesystem.opimpl import get_op_impl - ophandler = get_op_impl(opname) + ophandler = lloperation.LL_OPERATIONS[opname].fold setattr(self.__class__, 'op_' + opname, staticmethod(ophandler)) return ophandler # _______________________________________________________ @@ -887,37 +886,6 @@ raise RuntimeError("calling abstract method %r" % (m,)) return self.perform_call(m, (lltype.typeOf(inst),)+lltype.typeOf(m).ARGS, [inst]+args) - def op_ooupcast(self, INST, inst): - return ootype.ooupcast(INST, inst) - op_ooupcast.need_result_type = True - - def op_oodowncast(self, INST, inst): - return ootype.oodowncast(INST, inst) - op_oodowncast.need_result_type = True - - def op_oononnull(self, inst): - checkinst(inst) - return bool(inst) - - def op_oois(self, obj1, obj2): - if is_inst(obj1): - checkinst(obj2) - return obj1 == obj2 # NB. differently-typed NULLs must be equal - elif isinstance(obj1, ootype._class): - assert isinstance(obj2, ootype._class) - return obj1 is obj2 - else: - assert False, "oois on something silly" - - def op_instanceof(self, inst, INST): - return ootype.instanceof(inst, INST) - - def op_classof(self, inst): - return ootype.classof(inst) - - def op_subclassof(self, class1, class2): - return ootype.subclassof(class1, class2) - def op_ooidentityhash(self, inst): return ootype.ooidentityhash(inst) Modified: pypy/dist/pypy/rpython/lltypesystem/lloperation.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/lloperation.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/lloperation.py Sat Dec 16 11:29:25 2006 @@ -9,7 +9,7 @@ class LLOp(object): def __init__(self, sideeffects=True, canfold=False, canraise=(), - pyobj=False, canunwindgc=False, canrun=False): + pyobj=False, canunwindgc=False, canrun=False, oo=False): # self.opname = ... (set afterwards) if canfold: @@ -42,6 +42,9 @@ # The operation can be run directly with __call__ self.canrun = canrun or canfold + # The operation belongs to the ootypesystem + self.oo = oo + # __________ make the LLOp instances callable from LL helpers __________ __name__ = property(lambda self: 'llop_'+self.opname) @@ -62,7 +65,10 @@ global lltype # <- lazy import hack, worth an XXX from pypy.rpython.lltypesystem import lltype if self.canrun: - from pypy.rpython.lltypesystem.opimpl import get_op_impl + if self.oo: + from pypy.rpython.ootypesystem.ooopimpl import get_op_impl + else: + from pypy.rpython.lltypesystem.opimpl import get_op_impl op_impl = get_op_impl(self.opname) else: error = TypeError("cannot constant-fold operation %r" % ( @@ -404,10 +410,26 @@ 'instrument_count': LLOp(), # __________ ootype operations __________ - 'oosetfield': LLOp(), - 'oogetfield': LLOp(), - 'ooupcast': LLOp(), + 'new': LLOp(oo=True, canraise=(Exception,)), + 'runtimenew': LLOp(oo=True, canraise=(Exception,)), + 'oonewcustomdict': LLOp(oo=True, canraise=(Exception,)), + 'oosetfield': LLOp(oo=True), + 'oogetfield': LLOp(oo=True, sideeffects=False), + 'oosend': LLOp(oo=True, canraise=(Exception,)), + 'ooupcast': LLOp(oo=True, canfold=True), + 'oodowncast': LLOp(oo=True, canfold=True), + 'oononnull': LLOp(oo=True, canfold=True), + 'oois': LLOp(oo=True, canfold=True), + 'instanceof': LLOp(oo=True, canfold=True), + 'classof': LLOp(oo=True, canfold=True), + 'subclassof': LLOp(oo=True, canfold=True), + 'ooidentityhash': LLOp(oo=True, sideeffects=False), + 'oostring': LLOp(oo=True, sideeffects=False), + 'ooparse_int': LLOp(oo=True, canraise=(ValueError,)), + 'oohash': LLOp(oo=True, sideeffects=False), } +# ***** Run test_lloperation after changes. ***** + # __________ operations on PyObjects __________ Modified: pypy/dist/pypy/rpython/lltypesystem/test/test_lloperation.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/test/test_lloperation.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/test/test_lloperation.py Sat Dec 16 11:29:25 2006 @@ -1,18 +1,12 @@ import py from pypy.rpython.lltypesystem.lloperation import LL_OPERATIONS, llop from pypy.rpython.lltypesystem import lltype, opimpl +from pypy.rpython.ootypesystem import ootype, ooopimpl from pypy.rpython.llinterp import LLFrame from pypy.rpython.test.test_llinterp import interpret LL_INTERP_OPERATIONS = [name[3:] for name in LLFrame.__dict__.keys() - if name.startswith('op_') -# Ignore OO operations for now - and not (name == 'op_new' or - name == 'op_subclassof' or - name == 'op_instanceof' or - name == 'op_classof' or - name == 'op_runtimenew' or - name.startswith('op_oo'))] + if name.startswith('op_')] # ____________________________________________________________ @@ -20,7 +14,10 @@ for opname, llop in LL_OPERATIONS.items(): assert opname == llop.opname if llop.canfold: - func = opimpl.get_op_impl(opname) + if llop.oo: + func = ooopimpl.get_op_impl(opname) + else: + func = opimpl.get_op_impl(opname) assert callable(func) def test_llop_fold(): Added: pypy/dist/pypy/rpython/ootypesystem/ooopimpl.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/rpython/ootypesystem/ooopimpl.py Sat Dec 16 11:29:25 2006 @@ -0,0 +1,49 @@ +from pypy.rpython.ootypesystem import ootype + +# ____________________________________________________________ +# Implementation of the 'canfold' oo operations + + +def op_ooupcast(INST, inst): + return ootype.ooupcast(INST, inst) +op_ooupcast.need_result_type = True + +def op_oodowncast(INST, inst): + return ootype.oodowncast(INST, inst) +op_oodowncast.need_result_type = True + +def op_oononnull(inst): + checkinst(inst) + return bool(inst) + +def op_oois(obj1, obj2): + if is_inst(obj1): + checkinst(obj2) + return obj1 == obj2 # NB. differently-typed NULLs must be equal + elif isinstance(obj1, ootype._class): + assert isinstance(obj2, ootype._class) + return obj1 is obj2 + else: + assert False, "oois on something silly" + +def op_instanceof(inst, INST): + return ootype.instanceof(inst, INST) + +def op_classof(inst): + return ootype.classof(inst) + +def op_subclassof(class1, class2): + return ootype.subclassof(class1, class2) + + +def is_inst(inst): + return isinstance(ootype.typeOf(inst), (ootype.Instance, ootype.BuiltinType, ootype.StaticMethod)) + +def checkinst(inst): + assert is_inst(inst) + +# ____________________________________________________________ + +def get_op_impl(opname): + # get the op_xxx() function from the globals above + return globals()['op_' + opname] From guido at codespeak.net Sat Dec 16 15:30:58 2006 From: guido at codespeak.net (guido at codespeak.net) Date: Sat, 16 Dec 2006 15:30:58 +0100 (CET) Subject: [pypy-svn] r35833 - in pypy/dist/pypy/tool/build: . bin Message-ID: <20061216143058.0FC021007B@code0.codespeak.net> Author: guido Date: Sat Dec 16 15:30:55 2006 New Revision: 35833 Modified: pypy/dist/pypy/tool/build/bin/client pypy/dist/pypy/tool/build/build.py pypy/dist/pypy/tool/build/client.py Log: Added nasty hack to get rid of some code in pypy (using string replace) that used os.write during compilation (freezing the sandbox), added str() function to BuildRequest to not have so much blather in the logs (less verbose than the 'full' repr), added some missing channelwrapper.close() call that made the compilations block before the logs were sent over. The build farm now works (at least mostly) by just following the 'instructions' ('run bin/* scripts'). Modified: pypy/dist/pypy/tool/build/bin/client ============================================================================== --- pypy/dist/pypy/tool/build/bin/client (original) +++ pypy/dist/pypy/tool/build/bin/client Sat Dec 16 15:30:55 2006 @@ -11,6 +11,19 @@ from pypy.tool.build import build from pypy.config.config import to_optparse, Config +# XXX complete and total utter hack!!! to get some stuff out of pypy that +# basically freezes our execnet sandbox (because of using os.write to stderr +# and stuff) +replace_code_hack = """\ +path1 = '%s/pypy/translator/goal/targetpypystandalone.py' % (pypath,) +data = open(path1).read() +data = data.replace('os.write', 'pass # os.write') +open(path1, 'w').write(data) + +path2 = '%s/pypy/translator/goal/app_basic_example.py' % (pypath,) +open(path2, 'w').write('6 * 7\\n') +""" + def compile(wc, compileinfo): code = """\ import sys @@ -20,6 +33,9 @@ # interpolating the path pypath = %r +# XXX replace hack +%s + sys.path = [pypath] + sys.path os.chdir(pypath) @@ -29,14 +45,11 @@ # interpolating config compileinfo = %r +# log locally too log = open('/tmp/buildclient.log', 'a') outbuffer = OutputBuffer(log) -old_stdout = sys.__stdout__ -old_stderr = sys.__stderr__ sys.stdout = outbuffer sys.stderr = outbuffer -sys.__stdout__ = outbuffer -sys.__stderr__ = outbuffer try: try: from pypy.interpreter.error import OperationError @@ -67,8 +80,6 @@ else: channel.send(str(udir)) finally: - sys.__stdout__ = old_stdout - sys.__stderr__ = old_stderr sys.stdout = sys.__stdout__ sys.stderr = sys.__stderr__ log.close() @@ -78,10 +89,15 @@ gw = PopenGateway() buffercode = py.magic.autopath().dirpath().dirpath()\ .join('outputbuffer.py').read() - interpolated = code % (str(wc), buffercode, compileinfo) + interpolated = code % (str(wc), replace_code_hack, buffercode, compileinfo) channel = gw.remote_exec(interpolated) - upath = channel.receive() - output = channel.receive() + try: + upath = channel.receive() + output = channel.receive() + except channel.RemoteError, e: + print 'Remote exception:' + print str(e) + return (None, str(e)) channel.close() return upath, output Modified: pypy/dist/pypy/tool/build/build.py ============================================================================== --- pypy/dist/pypy/tool/build/build.py (original) +++ pypy/dist/pypy/tool/build/build.py Sat Dec 16 15:30:55 2006 @@ -83,7 +83,12 @@ self.svnrev = svnrev self.revrange = revrange + def __str__(self): + return '' % (self.svnurl, self.normalized_rev) + def __repr__(self): + """ the result of this method can be exec-ed when build.py is imported + """ return 'build.BuildRequest(%r, %r, %r, %r, %r, %r)' % ( self.email, self.sysinfo, self.compileinfo, self.svnurl, self.svnrev, self.revrange) Modified: pypy/dist/pypy/tool/build/client.py ============================================================================== --- pypy/dist/pypy/tool/build/client.py (original) +++ pypy/dist/pypy/tool/build/client.py Sat Dec 16 15:30:55 2006 @@ -129,4 +129,5 @@ print exc continue zip.close() + channelwrapper.close() From guido at codespeak.net Sat Dec 16 17:40:25 2006 From: guido at codespeak.net (guido at codespeak.net) Date: Sat, 16 Dec 2006 17:40:25 +0100 (CET) Subject: [pypy-svn] r35835 - in pypy/dist/pypy/tool/build: . bin test Message-ID: <20061216164025.CBF3F10084@code0.codespeak.net> Author: guido Date: Sat Dec 16 17:40:23 2006 New Revision: 35835 Modified: pypy/dist/pypy/tool/build/bin/client pypy/dist/pypy/tool/build/client.py pypy/dist/pypy/tool/build/server.py pypy/dist/pypy/tool/build/test/test_client.py Log: Removed the 'replace_code_hack' stuff after the problems with os.write were fixed in execnet (thanks, Armin!), moved stuff from bin/client to client.py so it can more easily be tested, some small cleanups and var renames. Modified: pypy/dist/pypy/tool/build/bin/client ============================================================================== --- pypy/dist/pypy/tool/build/bin/client (original) +++ pypy/dist/pypy/tool/build/bin/client Sat Dec 16 17:40:23 2006 @@ -1,28 +1,7 @@ #!/usr/bin/python import py -import path -import sys -import random -from pypy.tool.build import config as buildconfig - -from py.execnet import SshGateway, PopenGateway -from pypy.tool.build.client import init, zip_result -from pypy.tool.build import build -from pypy.config.config import to_optparse, Config - -# XXX complete and total utter hack!!! to get some stuff out of pypy that -# basically freezes our execnet sandbox (because of using os.write to stderr -# and stuff) -replace_code_hack = """\ -path1 = '%s/pypy/translator/goal/targetpypystandalone.py' % (pypath,) -data = open(path1).read() -data = data.replace('os.write', 'pass # os.write') -open(path1, 'w').write(data) - -path2 = '%s/pypy/translator/goal/app_basic_example.py' % (pypath,) -open(path2, 'w').write('6 * 7\\n') -""" +from py.execnet import PopenGateway def compile(wc, compileinfo): code = """\ @@ -33,9 +12,6 @@ # interpolating the path pypath = %r -# XXX replace hack -%s - sys.path = [pypath] + sys.path os.chdir(pypath) @@ -89,7 +65,7 @@ gw = PopenGateway() buffercode = py.magic.autopath().dirpath().dirpath()\ .join('outputbuffer.py').read() - interpolated = code % (str(wc), replace_code_hack, buffercode, compileinfo) + interpolated = code % (str(wc), buffercode, compileinfo) channel = gw.remote_exec(interpolated) try: upath = channel.receive() @@ -102,96 +78,10 @@ return upath, output -def tempdir(): - i = 0 - tmp = py.path.local('/tmp') - while 1: - dirname = 'buildtemp-%s' % (i,) - if not tmp.join(dirname).check(): - return tmp.ensure(dirname, dir=True) - i += 1 - -if buildconfig.server in ['localhost', '127.0.0.1']: - gw = PopenGateway() -else: - gw = SshGateway(buildconfig.server) - -channel = init(gw, - buildconfig.system_config, - path=buildconfig.path, - port=buildconfig.port) - -print channel.receive() # welcome message -try: - try: - while 1: - # receive compile requests - request = channel.receive() - if isinstance(request, str): - try: - request = build.BuildRequest.fromstring(request) - except (KeyError, SyntaxError), e: - print ('exception occurred when trying to interpret the ' - 'following request:') - print request - print - print 'going to continue' - continue - else: - raise ValueError( - 'received wrong unexpected data of type %s' % ( - type(request),) - ) - accepting = True - for checker in buildconfig.client_checkers: - if not checker(request): - if hasattr(checker, 'im_func'): - name = '%s.%s' % (checker.im_class.__name__, - checker.im_func.func_name) - else: - name = checker.func_name - print 'request refused by checker', name - accepting = False - break - channel.send(accepting) - if not accepting: - print 'refusing compilation' - continue - # XXX we should compile here, using data dict for info - print 'compilation requested for %s' % (request,) - - # subversion checkout - print 'checking out %s@%s' % (request.svnurl, - request.normalized_rev) - temp = tempdir() - svnwc = py.path.svnwc(temp) - svnwc.checkout(request.svnurl) - svnwc.update(request.normalized_rev) - - try: - print 'starting compilation' - upath, log = compile(svnwc, request.compileinfo) - except KeyboardInterrupt: - print 'quitting...' - break - - if upath: - # send over zip data, end with a None - print 'compilation successful, sending to server' - zip_result(py.path.local(upath), channel) - else: - print 'compilation failed, notifying server' - # just send the None - channel.send(None) - - # send over logs - print 'sending log' - channel.send(log) - - print 'done with compilation, waiting for next' - except EOFError: - sys.exit() -finally: - channel.close() - gw.exit() +if __name__ == '__main__': + # main bit + import path + from pypy.tool.build import config + from pypy.tool.build.client import main + main(config, path, compile) Modified: pypy/dist/pypy/tool/build/client.py ============================================================================== --- pypy/dist/pypy/tool/build/client.py (original) +++ pypy/dist/pypy/tool/build/client.py Sat Dec 16 17:40:23 2006 @@ -1,7 +1,8 @@ -import thread import py +import thread from zipfile import ZipFile from cStringIO import StringIO +from pypy.tool.build import build class PPBClient(object): def __init__(self, channel, sysinfo, testing=False): @@ -33,7 +34,6 @@ def wait_until_done(self, request): buildpath = self.server.get_new_buildpath(request) - open('/tmp/tessie', 'w').write('foo') if not self.testing: fp = buildpath.zipfile.open('w') @@ -45,7 +45,7 @@ chunk = self.channel.receive() except EOFError: # stop compilation, client has disconnected - return + return # end of data is marked by sending a None if chunk is None: break @@ -131,3 +131,100 @@ zip.close() channelwrapper.close() +def tempdir(parent=None): + i = 0 + if parent is None: + parent = py.path.local('/tmp') + while 1: + dirname = 'buildtemp-%s' % (i,) + if not parent.join(dirname).check(): + return parent.ensure(dirname, dir=True) + i += 1 + +def main(config, path, compilefunc): + from py.execnet import SshGateway, PopenGateway + + if config.server in ['localhost', '127.0.0.1']: + gw = PopenGateway() + else: + gw = SshGateway(config.server) + + channel = init(gw, + config.system_config, + path=config.path, + port=config.port) + + print channel.receive() # welcome message + try: + try: + while 1: + # receive compile requests + request = channel.receive() + if isinstance(request, str): + try: + request = build.BuildRequest.fromstring(request) + except (KeyError, SyntaxError), e: + print ('exception occurred when trying to ' + 'interpret the following request:') + print request + print + print 'going to continue' + continue + else: + raise ValueError( + 'received wrong unexpected data of type %s' % ( + type(request),) + ) + accepting = True + for checker in config.client_checkers: + if not checker(request): + if hasattr(checker, 'im_func'): + name = '%s.%s' % (checker.im_class.__name__, + checker.im_func.func_name) + else: + name = checker.func_name + print 'request refused by checker', name + accepting = False + break + channel.send(accepting) + if not accepting: + print 'refusing compilation' + continue + # XXX we should compile here, using data dict for info + print 'compilation requested for %s' % (request,) + + # subversion checkout + print 'checking out %s@%s' % (request.svnurl, + request.normalized_rev) + temp = tempdir() + svnwc = py.path.svnwc(temp) + svnwc.checkout(request.svnurl) + svnwc.update(request.normalized_rev) + + try: + print 'starting compilation' + upath, log = compilefunc(svnwc, request.compileinfo) + except KeyboardInterrupt: + print 'quitting...' + break + + if upath: + # send over zip data, end with a None + print 'compilation successful, sending to server' + zip_result(py.path.local(upath), channel) + else: + print 'compilation failed, notifying server' + # just send the None + channel.send(None) + + # send over logs + print 'sending log' + channel.send(log) + + print 'done with compilation, waiting for next' + except EOFError: + py.std.sys.exit() + finally: + channel.close() + gw.exit() + Modified: pypy/dist/pypy/tool/build/server.py ============================================================================== --- pypy/dist/pypy/tool/build/server.py (original) +++ pypy/dist/pypy/tool/build/server.py Sat Dec 16 17:40:23 2006 @@ -37,7 +37,7 @@ self._mailport = mailport self._mailfrom = mailfrom - self._buildpath = py.path.local(builddir) + self._buildroot = py.path.local(builddir) self._clients = [] done = [] @@ -49,8 +49,8 @@ bp.remove() self._done = done - self._queued = [] - self._waiting = [] + self._queued = [] # no compile client available + self._waiting = [] # compilation already in progress for someone else self._queuelock = thread.allocate_lock() self._namelock = thread.allocate_lock() @@ -88,7 +88,7 @@ for client in self._clients: if client.busy_on and request.has_satisfying_data(client.busy_on): self._channel.send('build for %s currently in progress' % - (request,)) + (request,)) self._waiting.append(request) return (False, 'this build is already in progress') # we don't have a build for this yet, find a client to compile it @@ -138,7 +138,7 @@ self._try_queued() def get_new_buildpath(self, request): - path = BuildPath(str(self._buildpath / self._create_filename())) + path = BuildPath(str(self._buildroot / self._create_filename())) path.request = request return path @@ -186,6 +186,9 @@ if request.has_satisfying_data(client.busy_on): break else: + # move request from 'waiting' (waiting for a compilation + # that is currently in progress) to 'queued' (waiting for + # a suitable build client to connect) self._waiting.remove(request) self._queued.append(request) continue @@ -214,7 +217,7 @@ try: today = time.strftime('%Y%m%d') buildnames = [p.basename for p in - py.path.local(self._buildpath).listdir()] + py.path.local(self._buildroot).listdir()] while True: name = '%s-%s-%s' % (self._projname, today, self._i) self._i += 1 Modified: pypy/dist/pypy/tool/build/test/test_client.py ============================================================================== --- pypy/dist/pypy/tool/build/test/test_client.py (original) +++ pypy/dist/pypy/tool/build/test/test_client.py Sat Dec 16 17:40:23 2006 @@ -4,6 +4,8 @@ import py import time import sys +from zipfile import ZipFile +from StringIO import StringIO from fake import FakeChannel, FakeServer class ClientForTests(client.PPBClient): @@ -80,3 +82,28 @@ assert br in c1.refused assert c1.busy_on == None +def test_zip_result(): + channel = FakeChannel() + tempdir = py.test.ensuretemp('zip_result') + tempdir.mkdir('foo') + tempdir.join('foo/bar.txt').write('bar') + + client.zip_result(tempdir, channel) + zip = StringIO() + while 1: + chunk = channel.receive() + if chunk is None: + break + zip.write(chunk) + + zip.seek(0) + zf = ZipFile(zip) + data = zf.read('foo/bar.txt') + assert data == 'bar' + +def test_tempdir(): + parent = py.test.ensuretemp('tempdir') + for i in range(10): + t = client.tempdir(parent) + assert t.basename == 'buildtemp-%s' % (i,) + From cfbolz at codespeak.net Sun Dec 17 13:10:24 2006 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Sun, 17 Dec 2006 13:10:24 +0100 (CET) Subject: [pypy-svn] r35838 - pypy/dist/pypy Message-ID: <20061217121024.5B5AB10076@code0.codespeak.net> Author: cfbolz Date: Sun Dec 17 13:10:22 2006 New Revision: 35838 Modified: pypy/dist/pypy/conftest.py Log: fix typo Modified: pypy/dist/pypy/conftest.py ============================================================================== --- pypy/dist/pypy/conftest.py (original) +++ pypy/dist/pypy/conftest.py Sun Dec 17 13:10:22 2006 @@ -45,7 +45,8 @@ if option.verbose: import traceback traceback.print_exc() - py.test.fail("fatal: cannot initialize objspace: %r" %(Space,)) + py.test.fail("fatal: cannot initialize objspace: %r" % + (config.objspace.name,)) _SPACECACHE[key] = space space.setitem(space.builtin.w_dict, space.wrap('AssertionError'), appsupport.build_pytest_assertion(space)) From cfbolz at codespeak.net Sun Dec 17 15:50:44 2006 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Sun, 17 Dec 2006 15:50:44 +0100 (CET) Subject: [pypy-svn] r35840 - in pypy/dist/pypy: config objspace/std objspace/std/test Message-ID: <20061217145044.404E510077@code0.codespeak.net> Author: cfbolz Date: Sun Dec 17 15:50:40 2006 New Revision: 35840 Modified: pypy/dist/pypy/config/pypyoption.py pypy/dist/pypy/objspace/std/dictmultiobject.py pypy/dist/pypy/objspace/std/test/test_dictmultiobject.py pypy/dist/pypy/objspace/std/test/test_dictobject.py Log: a very experimental dict implementation: try to make string-keyed dicts smaller by having them share a "structure". Modified: pypy/dist/pypy/config/pypyoption.py ============================================================================== --- pypy/dist/pypy/config/pypyoption.py (original) +++ pypy/dist/pypy/config/pypyoption.py Sun Dec 17 15:50:40 2006 @@ -97,6 +97,11 @@ default=False, requires=[("objspace.std.withstrdict", False)]), + BoolOption("withsharingdict", + "use dictionaries that share the keys part", + default=False, + requires=[("objspace.std.withmultidict", True)]), + BoolOption("withdictmeasurement", "create huge files with masses of information " "about dictionaries", Modified: pypy/dist/pypy/objspace/std/dictmultiobject.py ============================================================================== --- pypy/dist/pypy/objspace/std/dictmultiobject.py (original) +++ pypy/dist/pypy/objspace/std/dictmultiobject.py Sun Dec 17 15:50:40 2006 @@ -7,6 +7,17 @@ def _is_str(space, w_key): return space.is_w(space.type(w_key), space.w_str) +def _is_sane_hash(space, w_lookup_type): + """ Handles the case of a non string key lookup. + Types that have a sane hash/eq function should allow us to return True + directly to signal that the key is not in the dict in any case. + XXX The types should provide such a flag. """ + + # XXX there are much more types + return (space.is_w(w_lookup_type, space.w_NoneType) or + space.is_w(w_lookup_type, space.w_int)) + + # DictImplementation lattice # a dictionary starts with an EmptyDictImplementation, and moves down @@ -192,16 +203,6 @@ self.entries[0].w_value = w_value self.valid = 1 - def _is_sane_hash(self, w_lookup_type): - """ Handles the case of a non string key lookup. - Types that have a sane hash/eq function should allow us to return True - directly to signal that the key is not in the dict in any case. - XXX The types should provide such a flag. """ - - space = self.space - # XXX there are many more such types - return space.is_w(w_lookup_type, space.w_NoneType) or space.is_w(w_lookup_type, space.w_int) - def _lookup(self, key): assert isinstance(key, str) _hash = hash(key) @@ -270,7 +271,7 @@ return self else: raise KeyError - elif self._is_sane_hash(w_key_type): + elif _is_sane_hash(self.space, w_key_type): raise KeyError else: return self._convert_to_rdict().delitem(w_key) @@ -283,7 +284,7 @@ w_lookup_type = space.type(w_lookup) if space.is_w(w_lookup_type, space.w_str): return self._lookup(space.str_w(w_lookup)).w_value - elif self._is_sane_hash(w_lookup_type): + elif _is_sane_hash(self.space, w_lookup_type): return None else: return self._convert_to_rdict().get(w_lookup) @@ -329,7 +330,7 @@ return self else: return space.emptydictimpl - elif self._is_sane_hash(w_key_type): + elif _is_sane_hash(space, w_key_type): raise KeyError else: return self._as_rdict().delitem(w_key) @@ -342,7 +343,7 @@ w_lookup_type = space.type(w_lookup) if space.is_w(w_lookup_type, space.w_str): return self.content.get(space.str_w(w_lookup), None) - elif self._is_sane_hash(w_lookup_type): + elif _is_sane_hash(space, w_lookup_type): return None else: return self._as_rdict().get(w_lookup) @@ -367,15 +368,6 @@ space = self.space return [(space.wrap(key), w_value) for (key, w_value) in self.content.iteritems()] - def _is_sane_hash(self, w_lookup_type): - """ Handles the case of a non string key lookup. - Types that have a sane hash/eq function should allow us to return True - directly to signal that the key is not in the dict in any case. - XXX The types should provide such a flag. """ - - space = self.space - # XXX there are much more types - return space.is_w(w_lookup_type, space.w_NoneType) or space.is_w(w_lookup_type, space.w_int) def _as_rdict(self): newimpl = RDictImplementation(self.space) @@ -421,6 +413,146 @@ def items(self): return self.content.items() +class SharedStructure(object): + def __init__(self, keys=None, length=0, + other_structs=None, + last_key=None, + back_struct=None): + if keys is None: + keys = {} + self.keys = keys + self.length = length + self.back_struct = back_struct + if other_structs is None: + other_structs = [] + self.other_structs = other_structs + self.last_key = last_key + if last_key is not None: + assert back_struct is not None + self.propagating = False + + def new_structure(self, added_key): + keys = {} + for key, item in self.keys.iteritems(): + if item >= 0: + keys[key] = item + new_structure = SharedStructure(keys, self.length + 1, + [], added_key, self) + new_index = len(keys) + new_structure.keys[added_key] = new_index + self.keys[added_key] = ~len(self.other_structs) + self.other_structs.append(new_structure) + return new_structure + + +class State(object): + def __init__(self, space): + self.empty_structure = SharedStructure() + self.empty_structure.propagating = True + + +class SharedDictImplementation(DictImplementation): + + def __init__(self, space): + self.space = space + self.structure = space.fromcache(State).empty_structure + self.entries = [] + + def get(self, w_lookup): + space = self.space + w_lookup_type = space.type(w_lookup) + if space.is_w(w_lookup_type, space.w_str): + lookup = space.str_w(w_lookup) + i = self.structure.keys.get(lookup, -1) + if i < 0: + return None + return self.entries[i] + elif _is_sane_hash(space, w_lookup_type): + return None + else: + return self._as_rdict().get(w_lookup) + + def setitem(self, w_key, w_value): + space = self.space + if space.is_w(space.type(w_key), space.w_str): + return self.setitem_str(w_key, w_value) + else: + return self._as_rdict().setitem(w_key, w_value) + + def setitem_str(self, w_key, w_value): + m = ~len(self.structure.other_structs) + key = self.space.str_w(w_key) + i = self.structure.keys.get(key, m) + if i >= 0: + self.entries[i] = w_value + return self + if not self.structure.propagating: + return self._as_rdict(as_strdict=True).setitem_str(w_key, w_value) + if i == m: + new_structure = self.structure.new_structure(key) + else: + new_structure = self.structure.other_structs[~i] + new_structure.propagating = True + self.entries.append(w_value) + assert self.structure.length + 1 == new_structure.length + self.structure = new_structure + assert self.structure.keys[key] >= 0 + return self + + def delitem(self, w_key): + space = self.space + w_key_type = space.type(w_key) + if space.is_w(w_key_type, space.w_str): + key = space.str_w(w_key) + if (self.structure.last_key is not None and + key == self.structure.last_key): + self.entries.pop() + self.structure = self.structure.back_struct + return self + return self._as_rdict().delitem(w_key) + elif _is_sane_hash(space, w_key_type): + raise KeyError + else: + return self._as_rdict().delitem(w_key) + + def length(self): + return self.structure.length + + def iteritems(self): + return self._as_rdict().iteritems() + + def iterkeys(self): + return self._as_rdict().iterkeys() + + def itervalues(self): + return self._as_rdict().itervalues() + + def keys(self): + space = self.space + return [space.wrap(key) + for (key, item) in self.structure.keys.iteritems() + if item >= 0] + + def values(self): + return self.entries + + def items(self): + space = self.space + return [(space.wrap(key), self.entries[item]) + for (key, item) in self.structure.keys.iteritems() + if item >= 0] + + def _as_rdict(self, as_strdict=False): + if as_strdict: + newimpl = StrDictImplementation(self.space) + else: + newimpl = RDictImplementation(self.space) + for k, i in self.structure.keys.items(): + if i >= 0: + newimpl.setitem_str(self.space.wrap(k), self.entries[i]) + return newimpl + + import time, py class DictInfo(object): @@ -592,6 +724,8 @@ def __init__(w_self, space): if space.config.objspace.std.withdictmeasurement: w_self.implementation = MeasuringDictImplementation(space) + elif space.config.objspace.std.withsharingdict: + w_self.implementation = SharedDictImplementation(space) else: w_self.implementation = space.emptydictimpl Modified: pypy/dist/pypy/objspace/std/test/test_dictmultiobject.py ============================================================================== --- pypy/dist/pypy/objspace/std/test/test_dictmultiobject.py (original) +++ pypy/dist/pypy/objspace/std/test/test_dictmultiobject.py Sun Dec 17 15:50:40 2006 @@ -14,6 +14,16 @@ def setup_class(cls): cls.space = gettestobjspace(**{"objspace.std.withmultidict": True}) +class TestW_DictObject(test_dictobject.TestW_DictObject): + def setup_class(cls): + cls.space = gettestobjspace(**{"objspace.std.withsharingdict": True}) + +class AppTest_DictObject(test_dictobject.AppTest_DictObject): + def setup_class(cls): + cls.space = gettestobjspace(**{"objspace.std.withsharingdict": True}) + + + class FakeSpace(test_dictobject.FakeSpace): def str_w(self, string): assert isinstance(string, str) Modified: pypy/dist/pypy/objspace/std/test/test_dictobject.py ============================================================================== --- pypy/dist/pypy/objspace/std/test/test_dictobject.py (original) +++ pypy/dist/pypy/objspace/std/test/test_dictobject.py Sun Dec 17 15:50:40 2006 @@ -384,6 +384,7 @@ FakeSpace.config.objspace = Config() FakeSpace.config.objspace.std = Config() FakeSpace.config.objspace.std.withdictmeasurement = False +FakeSpace.config.objspace.std.withsharingdict = False from pypy.objspace.std.dictobject import getitem__Dict_ANY, setitem__Dict_ANY_ANY From cfbolz at codespeak.net Sun Dec 17 18:50:57 2006 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Sun, 17 Dec 2006 18:50:57 +0100 (CET) Subject: [pypy-svn] r35841 - in pypy/dist/pypy: interpreter objspace/std Message-ID: <20061217175057.1207810077@code0.codespeak.net> Author: cfbolz Date: Sun Dec 17 18:50:15 2006 New Revision: 35841 Modified: pypy/dist/pypy/interpreter/typedef.py pypy/dist/pypy/objspace/std/dictmultiobject.py Log: use the sharing dict only for instances Modified: pypy/dist/pypy/interpreter/typedef.py ============================================================================== --- pypy/dist/pypy/interpreter/typedef.py (original) +++ pypy/dist/pypy/interpreter/typedef.py Sun Dec 17 18:50:15 2006 @@ -183,7 +183,10 @@ def user_setup(self, space, w_subtype): self.space = space self.w__class__ = w_subtype - self.w__dict__ = space.newdict() + if space.config.objspace.std.withsharingdict: + from pypy.objspace.std import dictmultiobject + self.w__dict__ = dictmultiobject.W_DictMultiObject(space, + sharing=True) self.user_setup_slots(w_subtype.nslots) else: supercls = cls Modified: pypy/dist/pypy/objspace/std/dictmultiobject.py ============================================================================== --- pypy/dist/pypy/objspace/std/dictmultiobject.py (original) +++ pypy/dist/pypy/objspace/std/dictmultiobject.py Sun Dec 17 18:50:15 2006 @@ -598,7 +598,7 @@ self._dict_infos.append(self) def __repr__(self): args = [] - for k in sorted(self.__dict__): + for k in py.builtin.sorted(self.__dict__): v = self.__dict__[k] if v != 0: args.append('%s=%r'%(k, v)) @@ -721,10 +721,10 @@ class W_DictMultiObject(W_Object): from pypy.objspace.std.dicttype import dict_typedef as typedef - def __init__(w_self, space): + def __init__(w_self, space, sharing=False): if space.config.objspace.std.withdictmeasurement: w_self.implementation = MeasuringDictImplementation(space) - elif space.config.objspace.std.withsharingdict: + elif space.config.objspace.std.withsharingdict and sharing: w_self.implementation = SharedDictImplementation(space) else: w_self.implementation = space.emptydictimpl From cfbolz at codespeak.net Mon Dec 18 11:09:28 2006 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Mon, 18 Dec 2006 11:09:28 +0100 (CET) Subject: [pypy-svn] r35843 - pypy/dist/pypy/interpreter Message-ID: <20061218100928.5AED310074@code0.codespeak.net> Author: cfbolz Date: Mon Dec 18 11:09:26 2006 New Revision: 35843 Modified: pypy/dist/pypy/interpreter/typedef.py Log: argh! sorry for this. Add the missing attribute in the other case. Modified: pypy/dist/pypy/interpreter/typedef.py ============================================================================== --- pypy/dist/pypy/interpreter/typedef.py (original) +++ pypy/dist/pypy/interpreter/typedef.py Mon Dec 18 11:09:26 2006 @@ -187,6 +187,8 @@ from pypy.objspace.std import dictmultiobject self.w__dict__ = dictmultiobject.W_DictMultiObject(space, sharing=True) + else: + self.w__dict__ = space.newdict() self.user_setup_slots(w_subtype.nslots) else: supercls = cls From ericvrp at codespeak.net Mon Dec 18 11:55:14 2006 From: ericvrp at codespeak.net (ericvrp at codespeak.net) Date: Mon, 18 Dec 2006 11:55:14 +0100 (CET) Subject: [pypy-svn] r35844 - in pypy/dist/pypy/jit/codegen/llvm: . test Message-ID: <20061218105514.6273010074@code0.codespeak.net> Author: ericvrp Date: Mon Dec 18 11:55:12 2006 New Revision: 35844 Modified: pypy/dist/pypy/jit/codegen/llvm/rgenop.py pypy/dist/pypy/jit/codegen/llvm/test/test_rgenop.py Log: Switch support for jit/codegen/llvm Modified: pypy/dist/pypy/jit/codegen/llvm/rgenop.py ============================================================================== --- pypy/dist/pypy/jit/codegen/llvm/rgenop.py (original) +++ pypy/dist/pypy/jit/codegen/llvm/rgenop.py Mon Dec 18 11:55:12 2006 @@ -201,83 +201,37 @@ lines.append('}') -class FlexSwitch(CodeGenSwitch): +class FlexSwitch(Block): - def __init__(self, rgenop): - log('FlexSwitch.__init__') + def __init__(self, rgenop, builder, gv_exitswitch): + log('%s FlexSwitch.__init__ %s' % (builder.block.label, gv_exitswitch.operand())) self.rgenop = rgenop - #self.default_case_addr = 0 + self.builder = builder + self.gv_exitswitch = gv_exitswitch - def initialize(self, builder, gv_exitswitch): - log('FlexSwitch.initialize TODO') - #mc = builder.mc - #mc.MOV(eax, gv_exitswitch.operand(builder)) - #self.saved_state = builder._save_state() - #self._reserve(mc) - - def _reserve(self, mc): - log('FlexSwitch._reserve TODO') - #RESERVED = 11*4+5 # XXX quite a lot for now :-/ - #pos = mc.tell() - #mc.UD2() - #mc.write('\x00' * (RESERVED-1)) - #self.nextfreepos = pos - #self.endfreepos = pos + RESERVED - - def _reserve_more(self): - log('FlexSwitch._reserve_more TODO') - #start = self.nextfreepos - #end = self.endfreepos - #newmc = self.rgenop.open_mc() - #self._reserve(newmc) - #self.rgenop.close_mc(newmc) - #fullmc = InMemoryCodeBuilder(start, end) - #fullmc.JMP(rel32(self.nextfreepos)) - #fullmc.done() + self.default_label = None + self.cases = [] + + self.rgenop.blocklist.append(self) def add_case(self, gv_case): - log('FlexSwitch.add_case TODO') - #rgenop = self.rgenop - #targetbuilder = Builder._new_from_state(rgenop, self.saved_state) - #target_addr = targetbuilder.mc.tell() - #try: - # self._add_case(gv_case, target_addr) - #except CodeBlockOverflow: - # self._reserve_more() - # self._add_case(gv_case, target_addr) - #return targetbuilder - - def _add_case(self, gv_case, target_addr): - log('FlexSwitch._add_case TODO') - #start = self.nextfreepos - #end = self.endfreepos - #mc = InMemoryCodeBuilder(start, end) - #mc.CMP(eax, gv_case.operand(None)) - #mc.JE(rel32(target_addr)) - #pos = mc.tell() - #if self.default_case_addr: - # mc.JMP(rel32(self.default_case_addr)) - #else: - # illegal_start = mc.tell() - # mc.JMP(rel32(0)) - # ud2_addr = mc.tell() - # mc.UD2() - # illegal_mc = InMemoryCodeBuilder(illegal_start, end) - # illegal_mc.JMP(rel32(ud2_addr)) - #mc.done() - #self.nextfreepos = pos + targetbuilder = self.builder._fork() + self.cases.append('%s,label %%%s' % (gv_case.operand(), targetbuilder.nextlabel)) + log('%s FlexSwitch.add_case %s => %s' % ( + self.builder.block.label, gv_case.operand(), targetbuilder.nextlabel)) + return targetbuilder def add_default(self): - log('FlexSwitch.add_default TODO') - #rgenop = self.rgenop - #targetbuilder = Builder._new_from_state(rgenop, self.saved_state) - #self.default_case_addr = targetbuilder.mc.tell() - #start = self.nextfreepos - #end = self.endfreepos - #mc = InMemoryCodeBuilder(start, end) - #mc.JMP(rel32(self.default_case_addr)) - #mc.done() - #return targetbuilder + targetbuilder = self.builder._fork() + self.default_label = targetbuilder.nextlabel + log('%s FlexSwitch.add_default => %s' % ( + self.builder.block.label, targetbuilder.nextlabel)) + return targetbuilder + + def writecode(self, lines): + #note: gv_exitswitch should be an integer! (cast might be required here) + lines.append(' switch %s,label %%%s [%s]' % ( + self.gv_exitswitch.operand(), self.default_label, ' '.join(self.cases))) class Builder(object): #changed baseclass from (GenBuilder) for better error messages @@ -298,6 +252,12 @@ def end(self): self.rgenop.end() # XXX Hack to be removed! + def pause(self): + log('%s Builder.pause' % self.block.label) + + def resume(self): + log('%s Builder.resume' % self.block.label) + # ---------------------------------------------------------------- # The public Builder interface @@ -489,9 +449,10 @@ #/XXX def enter_next_block(self, kinds, args_gv): - # if nextlabel is None, it means that we are currently - # generating a block; in this case we need to put a br - # to go to the next block + # if nextlabel is None, it means that we still need to + # properly terminate the current block (with a br to go + # to the next block) + # see: http://llvm.org/docs/LangRef.html#terminators if self.nextlabel is None: self.nextlabel = count.newlabel() self.asm.append(' br label %%%s' % (self.nextlabel,)) @@ -675,15 +636,7 @@ def flexswitch(self, gv_exitswitch): log('%s Builder.flexswitch %s' % (self.block.label, gv_exitswitch.operand())) - self.asm.append(' ;flexswitch ' + gv_exitswitch.operand()) - result = FlexSwitch(self.rgenop) - result.initialize(self, gv_exitswitch) - self._close() - return result - - def show_incremental_progress(self): - log('%s Builder.show_incremental_progress' % self.label.operand()) - pass + return FlexSwitch(self.rgenop, self, gv_exitswitch) class RLLVMGenOp(object): #changed baseclass from (AbstractRGenOp) for better error messages Modified: pypy/dist/pypy/jit/codegen/llvm/test/test_rgenop.py ============================================================================== --- pypy/dist/pypy/jit/codegen/llvm/test/test_rgenop.py (original) +++ pypy/dist/pypy/jit/codegen/llvm/test/test_rgenop.py Mon Dec 18 11:55:12 2006 @@ -15,9 +15,3 @@ py.test.skip('WIP') test_fact_compile = skip #XXX Blocked block, introducted by this checkin (I don't understand) - - test_switch_direct = skip - test_switch_compile = skip - - test_large_switch_direct = skip - test_large_switch_compile = skip From santagada at codespeak.net Mon Dec 18 14:26:37 2006 From: santagada at codespeak.net (santagada at codespeak.net) Date: Mon, 18 Dec 2006 14:26:37 +0100 (CET) Subject: [pypy-svn] r35846 - in pypy/dist/pypy/lang/js: . test Message-ID: <20061218132637.C3FAC1005A@code0.codespeak.net> Author: santagada Date: Mon Dec 18 14:26:25 2006 New Revision: 35846 Added: pypy/dist/pypy/lang/js/jsparser.py - copied, changed from r35838, pypy/dist/pypy/lang/js/parser.py pypy/dist/pypy/lang/js/reference.py Removed: pypy/dist/pypy/lang/js/parser.py pypy/dist/pypy/lang/js/scope.py Modified: pypy/dist/pypy/lang/js/astgen.py pypy/dist/pypy/lang/js/context.py pypy/dist/pypy/lang/js/interpreter.py pypy/dist/pypy/lang/js/jsobj.py pypy/dist/pypy/lang/js/test/test_interp.py pypy/dist/pypy/lang/js/test/test_parser.py Log: Lots of changes, new context and base object to support nested scopes and properprototyping WARNING: Non working code for now. Modified: pypy/dist/pypy/lang/js/astgen.py ============================================================================== --- pypy/dist/pypy/lang/js/astgen.py (original) +++ pypy/dist/pypy/lang/js/astgen.py Mon Dec 18 14:26:25 2006 @@ -107,8 +107,6 @@ class Script(Node): def __init__(self, nodes, var_decl, func_decl): self.nodes = nodes - import pdb - #pdb.set_trace() [scope_manager.add_variable(id.name, w_Undefined) for id in var_decl] [scope_manager.add_variable(id.name, id) for id in func_decl] self.var_decl = var_decl @@ -159,6 +157,21 @@ def build_interpreter(d): return from_dict(d) +# FIXME: Continue the translation from if/elif to this dict map +build_map = {'ARRAY_INIT':Array, + 'ASSIGN': Assign, + 'BLOCK': Block} + +def from_dict_map(d): + if d is None: + return d + try: + build_map[d['type']](d) + except KeyError,e: + raise NotImplementedError("Don't know how to handle %s" %(d['type'],)) + + + def from_dict(d): if d is None: return d Modified: pypy/dist/pypy/lang/js/context.py ============================================================================== --- pypy/dist/pypy/lang/js/context.py (original) +++ pypy/dist/pypy/lang/js/context.py Mon Dec 18 14:26:25 2006 @@ -1,23 +1,25 @@ class ExecutionContext(object): - - def __init__(self, parent = None): - self.parent = parent - self.locals = {} - if parent is None: - self.globals = {} - else: - self.globals = parent.globals - - def assign(self, name, value): - if (name not in self.locals) and (name in self.globals): - self.globals[name] = value - else: - self.locals[name] = value - - def access(self, name): - if name in self.locals: - return self.locals[name] - elif name in self.globals: - return self.globals[name] - raise NameError("%s is not declared" % name) + def __init__(self): + self.scope = [] + self.this = None + self.variable = None + self.property = Property('',w_Undefined) #Attribute flags for new vars + + def get_identifier(self, identifier): + """docstring for get_identifier""" + pass + + + + +class GlobalContext(ExecutionContext): + """docstring for GlobalContext""" + def __init__(self, global): + ExecutionContext.__init__() + self.scope.append(global) + self.this = global + self.variable = global + + + Modified: pypy/dist/pypy/lang/js/interpreter.py ============================================================================== --- pypy/dist/pypy/lang/js/interpreter.py (original) +++ pypy/dist/pypy/lang/js/interpreter.py Mon Dec 18 14:26:25 2006 @@ -3,7 +3,6 @@ from pypy.lang.js.context import ExecutionContext from pypy.lang.js.jsobj import W_Number, W_String, W_Object from pypy.lang.js.jsobj import w_Undefined, W_Arguments, W_Boolean, NaN -from pypy.lang.js.scope import scope_manager def writer(x): print x @@ -17,6 +16,27 @@ self.exception = exception self.args = self.exception +class Interpreter(object): + """Creates a js interpreter""" + def __init__(self, script_source=None): + self.w_Object = W_Object() #creating Object + self.w_Global = W_Object() + w_Global.Prototype = w_Object + w_Global.Set('prototype', 'Object') + w_Global.Set('Object', w_Object) + self.global_context = GlobalContext(w_global) + if script_source is not none: + self.load_source(script_source) + + def load_source(self, script_source): + """load a source script text to the interpreter""" + pass + + def run(self): + """run the interpreter""" + pass + + class __extend__(Array): def call(self, context): @@ -25,10 +45,7 @@ class __extend__(Assign): def call(self, context): - print context.locals.keys(), "|||||", context.globals - print context.locals['this'] val = self.expr.call(context) - print val self.identifier.put(context,val) class __extend__(Block): @@ -93,9 +110,7 @@ if self.initialiser is not None: context.assign(self.name, self.initialiser.call(context)) try: - print "trying to access", self.name value = context.access(self.name) - print "value", value return value except NameError: return scope_manager.get_variable(self.name) @@ -179,9 +194,6 @@ obj.Class = 'Object' #it should be undefined... to be completed obj.dict_w['prototype'] = constructor.dict_w['prototype'] - #nctx = ExecutionContext(context) - #nctx.assign('this',obj) - #print nctx.locals.keys() constructor.Call(context, this = obj) return obj @@ -203,9 +215,6 @@ w_expr = property.value.call(context).GetValue() w_obj.Put(name, w_expr) return w_obj - #dict_w = {} - #for property in self.properties: - # dict_w[property.name class __extend__(Plus): def call(self, context=None): Modified: pypy/dist/pypy/lang/js/jsobj.py ============================================================================== --- pypy/dist/pypy/lang/js/jsobj.py (original) +++ pypy/dist/pypy/lang/js/jsobj.py Mon Dec 18 14:26:25 2006 @@ -5,6 +5,21 @@ INFDEF = 1e300 * 1e300 NaN = INFDEF/INFDEF +# TODO: Use an integer for attributes +class Properfty(object): + def __init__(self, name, value, DontDelete=False, + ReadOnly=False, DontEnum=False, Internal=False): + self.name = name + self.value = value + self.DontDelete = DontDelete + self.ReadOnly = ReadOnly + self.DontEnum = DontEnum + self.Internal = Internal + +def internal_property(name, value): + """return a internal property with the right attributes""" + return Property(name, value, True, True, True, True) + class W_Root(object): def GetValue(self): return self @@ -27,75 +42,84 @@ def __repr__(self): return "<%s(%s)>" % (self.__class__.__name__, str(self)) +class W_Primitive(W_Root): + """unifying parent for primitives""" + pass + class W_Object(W_Root): - def __init__(self, dict_w, function=None): - # string --> W_Root - self.dict_w = dict_w - # XXX: more stuff - self.dict_w['toString'] = W_Builtin({}, self.w_string) - # XXX A bit hairy here, we store here a Function, and Script - # is a self.function.body - self.dict_w['prototype'] = self + def __init__(self, function=None): + self.propdict = {} + self.propdict['toString'] = Property('toString', + W_Builtin(self.__str__)) # FIXME: Not working + self.propdict['prototype'] = Property('prototype', w_Undefined, + DontDelete=True) + self.Prototype = None + self.Class = "Object" self.function = function - #self.class_ = None - - def Call(self, context, args=[], this = None): - if self.function: - return self.function.body.call(context=context, - args=args, - - params= self.function.params, - this = this - ) + self.scope = [] + + def Call(self, context, args=[], this = None): # FIXME: Context-ng + if self.function is not none: + return self.function.body.call(context=context, args=args, + params=self.function.params, + this=this) else: print "returning common object" - return W_Object({}) - - def w_string(self): - return W_String(str(self)) - - def DefaultValue(self, hint): - #if hint == "string": - tostring_meth = self.Get("toString") - if isinstance(tostring_meth, W_Object): - return tostring_meth.Call(this=self) - valueof_meth = self.Get("valueOf") - if isinstance(valueof_meth, W_Object): - retval = valueof_meth.Call(this=self) - # XXX: check primitiveness of retval - return retval - return w_Undefined - - def ToPrimitive(self, hint=""): - return self.DefaultValue(hint) - - def ToNumber(self): - return self.ToPrimitive("number").ToNumber(hint="number") - - def ToString(self): - return str(self.DefaultValue(hint="string")) - - def Get(self, name): - if name in self.dict_w: - return self.dict_w[name] - - return w_Undefined - - def CanPut(self, name): + return W_Object() + + def Get(self, P): + if P in self.propdict: return self.propdict[P].value + if self.prototype is None: return w_Undefined + return self.prototype.Get(P) # go down the prototype chain + + def CanPut(self, P): + if P in self.propdict: + if self.propdict[P].ReadOnly: return False + return True + if self.Prototype is None: return True + return self.Prototype.CanPut(P) + + def Put(self, P, V): + if not self.CanPut(P): return + if P in self.propdict: + self.propdict[P].value = V + else: + self.propdict[P] = Property(P, V) + + def HasProperty(self, P): + if P in self.propdict: return True + if self.Prototype is None: return False + return self.Prototype.HasProperty(P) + + def Delete(P): + if P in self.propdict: + if self.propdict[P].DontDelete: return False + self.propdict.pop(P) + return True return True - - def Put(self, name, w_obj): - # INSANE - raise some exceptions in case of read only and such - print "We are insane" - if not self.CanPut(name): - return # AAAAAAAAAAAAaaaaaaaaaaaa - print name,"=", w_obj - self.dict_w[name] = w_obj - + + def DefaultValue(self, hint): + def internal_def_value(tryone, trytwo): + t1 = self.Get(tryone) + if isinstance(t1, W_Object): + val = t1.Call(this=self) + if isinstance(val, W_Primitive): + return val + t2 = self.Get(trytwo) + if isinstance(t2, W_Object): + val = t2.Call(this=self) + if isinstance(val, W_Primitive): + return val + raise jsTypeError + + if hint == "String": + internal_def_value("toString", "valueOf") + else: #suppose hint is "Number" dunno what to do otherwise + internal_def_value("valueOf", "toString") + def __str__(self): - # INSANE - return "[object Object]" - + return "[object %s]"%(self.Class,) + class W_Arguments(W_Object): pass @@ -137,14 +161,12 @@ class W_String(W_Root): def __init__(self, strval): - # XXX: Should be unicode object self.strval = strval # def ToString(self): # return self.strval def __str__(self): - # INSANE - should be like 'str' or so return self.strval def ToBoolean(self): @@ -178,12 +200,12 @@ raise NotImplementedError("W_Reference.GetValue") class W_Builtin(W_Object): - def __init__(self, dict_w, internalfunction): - self.dict_w = {} - self.internalfunction = internalfunction + def __init__(self, builtinfunction): + W_Object.__init__() + self.builtinfunction = builtinfunction - def Call(self, this=None): - return self.internalfunction() + def Call(self, context, args=[], this = None): + return self.builtinfunction(*args) class W_List(W_Root): def __init__(self, list_w): @@ -197,3 +219,12 @@ w_Undefined = W_Undefined() w_Null = W_Null() + +def to_primitive(Value, PreferredType): + assert isinstance(Value, W_Root) + if isinstance(Value, W_Object): + return Value.DefaultValue(PreferredType) + return Value + + + \ No newline at end of file Added: pypy/dist/pypy/lang/js/reference.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/lang/js/reference.py Mon Dec 18 14:26:25 2006 @@ -0,0 +1,28 @@ +#!/usr/bin/env python +# encoding: utf-8 +""" +reference.py + +Created by Leonardo Santagada on 2006-12-16. +""" + +class Reference(object): + """Reference Type""" + def __init__(self, propertyname, baseobject=None): + self.baseobject = baseobject + self.propertyname = propertyname + +def get_value(v): + if not type(v, Reference): + return v + if v.baseobject is None: + raise ReferenceError + return v.baseobject.get(v.propertyname) + +def put_value(v, w): + if not type(v, Reference): + raise ReferenceError + base = v.baseobject + if v.baseobject is None: + base = get_global() #gets the global object of js + base.put(v.propertyname, w) \ No newline at end of file Modified: pypy/dist/pypy/lang/js/test/test_interp.py ============================================================================== --- pypy/dist/pypy/lang/js/test/test_interp.py (original) +++ pypy/dist/pypy/lang/js/test/test_interp.py Mon Dec 18 14:26:25 2006 @@ -1,7 +1,7 @@ from pypy.lang.js.astgen import * from pypy.lang.js import interpreter -from pypy.lang.js.parser import parse +from pypy.lang.js.jsparser import parse from pypy.lang.js.interpreter import ThrowException from pypy.lang.js.jsobj import W_Number, W_Object from pypy.lang.js.context import ExecutionContext Modified: pypy/dist/pypy/lang/js/test/test_parser.py ============================================================================== --- pypy/dist/pypy/lang/js/test/test_parser.py (original) +++ pypy/dist/pypy/lang/js/test/test_parser.py Mon Dec 18 14:26:25 2006 @@ -1,4 +1,4 @@ -from pypy.lang.js.parser import read_js_output, JsSyntaxError, parse +from pypy.lang.js.jsparser import read_js_output, JsSyntaxError, parse from pypy.lang.js.test.test_interp import js_is_on_path import py From santagada at codespeak.net Mon Dec 18 14:36:56 2006 From: santagada at codespeak.net (santagada at codespeak.net) Date: Mon, 18 Dec 2006 14:36:56 +0100 (CET) Subject: [pypy-svn] r35848 - pypy/dist/pypy/lang/js/test Message-ID: <20061218133656.D95321005A@code0.codespeak.net> Author: santagada Date: Mon Dec 18 14:36:50 2006 New Revision: 35848 Removed: pypy/dist/pypy/lang/js/test/test_scope.py Modified: pypy/dist/pypy/lang/js/test/test_interp.py Log: deleted some tests and skiped others Modified: pypy/dist/pypy/lang/js/test/test_interp.py ============================================================================== --- pypy/dist/pypy/lang/js/test/test_interp.py (original) +++ pypy/dist/pypy/lang/js/test/test_interp.py Mon Dec 18 14:36:50 2006 @@ -10,6 +10,8 @@ import sys from StringIO import StringIO +py.test.skip("not finished yet") + def parse_d(code): return build_interpreter(parse(code)) From arigo at codespeak.net Mon Dec 18 14:47:20 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 18 Dec 2006 14:47:20 +0100 (CET) Subject: [pypy-svn] r35849 - pypy/dist/pypy/jit/codegen/i386 Message-ID: <20061218134720.7EC0710061@code0.codespeak.net> Author: arigo Date: Mon Dec 18 14:47:19 2006 New Revision: 35849 Modified: pypy/dist/pypy/jit/codegen/i386/rgenop.py pypy/dist/pypy/jit/codegen/i386/ri386setup.py Log: (pedronis, arre, arigo) Fixed the stack alignment code. If the DEBUG_CALL_ALIGN variable is True, add a run-time sanity check. Note: if the test fail you get a signal that is reported as "Floating point error" :-/ 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 Mon Dec 18 14:47:19 2006 @@ -9,6 +9,7 @@ from pypy.rpython.annlowlevel import llhelper WORD = 4 +DEBUG_CALL_ALIGN = True if sys.platform == 'darwin': CALL_ALIGN = 4 else: @@ -18,16 +19,17 @@ def __init__(self, stackpos): # 'stackpos' is an index relative to the pushed arguments - # (where N is the number of arguments of the function): + # (where N is the number of arguments of the function + # and B is a small integer for stack alignment purposes): # - # 0 = last arg - # = ... - # N-1 = 1st arg - # N = return address - # N+1 = local var - # N+2 = ... - # ... <--- esp+4 - # local var <--- esp + # B + 0 = last arg + # = ... + # B +N-1 = 1st arg + # B + N = return address + # B +N+1 = local var + # B +N+2 = ... + # ... <--- esp+4 + # local var <--- esp # self.stackpos = stackpos @@ -292,7 +294,9 @@ self._open() numargs = sigtoken # for now #self.mc.BREAKPOINT() - return [Var(pos) for pos in range(numargs-1, -1, -1)] + # self.stackdepth-1 is the return address; the arguments + # come just before + return [Var(self.stackdepth-2-n) for n in range(numargs)] def _close(self): self.closed = True @@ -428,13 +432,18 @@ MASK = CALL_ALIGN-1 if MASK: final_depth = self.stackdepth + numargs - delta = (final_depth+MASK)&~MASK-final_depth + delta = ((final_depth+MASK)&~MASK)-final_depth if delta: self.mc.SUB(esp, imm(delta*WORD)) self.stackdepth += delta for i in range(numargs-1, -1, -1): gv_arg = args_gv[i] self.push(gv_arg.operand(self)) + if DEBUG_CALL_ALIGN: + self.mc.MOV(eax, esp) + self.mc.AND(eax, imm8((WORD*CALL_ALIGN)-1)) + self.mc.ADD(eax, imm32(sys.maxint)) # overflows unless eax == 0 + self.mc.INTO() if gv_fnptr.is_const: target = gv_fnptr.revealconst(lltype.Signed) self.mc.CALL(rel32(target)) @@ -481,8 +490,7 @@ def finish_and_return(self, sigtoken, gv_returnvar): self._open() - numargs = sigtoken # for now - initialstackdepth = numargs + 1 + initialstackdepth = self.rgenop._initial_stack_depth(sigtoken) self.mc.MOV(eax, gv_returnvar.operand(self)) self.mc.ADD(esp, imm(WORD * (self.stackdepth - initialstackdepth))) self.mc.RET() @@ -985,14 +993,25 @@ return Builder(self, stackdepth) def newgraph(self, sigtoken, name): - numargs = sigtoken # for now - initialstackdepth = numargs+1 - builder = self.openbuilder(initialstackdepth) + builder = self.openbuilder(self._initial_stack_depth(sigtoken)) builder._open() # Force builder to have an mc entrypoint = builder.mc.tell() inputargs_gv = builder._write_prologue(sigtoken) return builder, IntConst(entrypoint), inputargs_gv + def _initial_stack_depth(self, sigtoken): + # If a stack depth is a multiple of CALL_ALIGN then the + # arguments are correctly aligned for a call. We have to + # precompute initialstackdepth to guarantee that. For OS/X the + # convention is that the stack should be aligned just after all + # arguments are pushed, i.e. just before the return address is + # pushed by the CALL instruction. In other words, after + # 'numargs' arguments have been pushed the stack is aligned: + numargs = sigtoken # for now + MASK = CALL_ALIGN - 1 + initialstackdepth = ((numargs+MASK)&~MASK) + 1 + return initialstackdepth + def replay(self, label, kinds): return ReplayBuilder(self), [dummy_var] * len(kinds) 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 Mon Dec 18 14:47:19 2006 @@ -414,6 +414,9 @@ INT = Instruction() INT.mode1(IMM8, ['\xCD', immediate(1, 'b')]) +INTO = Instruction() +INTO.mode0(['\xCE']) + BREAKPOINT = Instruction() # INT 3 BREAKPOINT.mode0(['\xCC']) BREAKPOINT.as_alias = "INT3" From arigo at codespeak.net Mon Dec 18 17:16:18 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 18 Dec 2006 17:16:18 +0100 (CET) Subject: [pypy-svn] r35855 - pypy/dist/pypy/doc Message-ID: <20061218161618.9E4C01006F@code0.codespeak.net> Author: arigo Date: Mon Dec 18 17:16:16 2006 New Revision: 35855 Modified: pypy/dist/pypy/doc/draft-jit-outline.txt Log: Slight expansion of the timeshifter introduction. Modified: pypy/dist/pypy/doc/draft-jit-outline.txt ============================================================================== --- pypy/dist/pypy/doc/draft-jit-outline.txt (original) +++ pypy/dist/pypy/doc/draft-jit-outline.txt Mon Dec 18 17:16:16 2006 @@ -76,7 +76,7 @@ Terminology -========================================= +---------------------------------- Partial evaluation is the process of evaluating a function, say ``f(x, y)``, with only partial information about the value of its arguments, @@ -375,25 +375,34 @@ Once binding times (colors) have been assigned to all variables in a family of control flow graphs, the next step is to mutate the graphs accordingly. This process is called *timeshifting*, because it changes -the time at which the graphs are meant to be run. So far, the graphs -implemented some kind of interpreter; they were meant to execute at -run-time, and directly computed the intended result and side-effects. -After timeshifting, the graphs are logically very different: they are -intended to be executed at compile-time, and their only side effects is -to produce residual code. The residual code itself can later be -executed at run-time. - -Despite the difference, though, the timeshifted graphs are formally -close to the original graphs. The rest of this section describes this -timeshifting process in more detail. +the time at which the graphs are meant to be run. + +Keep in mind that the program described as the "source RPython program" +in this document is typically an interpreter - the canonical example is +that it is the whole `PyPy Standard Interpreter`_. This program, +considered as a forest of control flow graphs, implements a typical +interpreter: the flow graphs are meant to execute at run-time, and +directly compute the intended result and side-effects. These are the +flow graphs that we process (and not the application-level program, +which cannot be expressed as low-level flow graphs anyway). + +After being timeshifted, the graphs of our interpreter become logically +very different: they are no longer intended to be executed at run-time, +but just ahead of it (what we call "compile-time"). Their only side +effects is to produce residual code. The residual code itself runs "at +run-time". + +Despite the conceptual difference, though, the timeshifted graphs are +formally close to the original graphs. The rest of this section +describes this timeshifting process in more detail. Red and Green Operations -------------------------- -The basic idea of timeshifting is to transform operations depending on -the color of their operands and result. Variables themselves need to -be represented based on their color: +The basic idea of timeshifting is to transform operations in a way that +depends on the color of their operands and result. Variables themselves +need to be represented based on their color: * The green variables are the compile-time variables. Their values are meant to be available during compile-time already. A variable that @@ -475,6 +484,7 @@ __ `Example above`_ + Support code -------------- @@ -658,5 +668,6 @@ .. _`annotator`: dynamic-language-translation.html .. _`specialization of functions`: dynamic-language-translation.html#specialization .. _Psyco: http://psyco.sourceforge.net +.. _`PyPy Standard Interpreter`: architecture.html#standard-interpreter .. include:: _ref.txt From pedronis at codespeak.net Mon Dec 18 17:31:34 2006 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Mon, 18 Dec 2006 17:31:34 +0100 (CET) Subject: [pypy-svn] r35856 - pypy/dist/pypy/doc Message-ID: <20061218163134.C79A310072@code0.codespeak.net> Author: pedronis Date: Mon Dec 18 17:31:33 2006 New Revision: 35856 Modified: pypy/dist/pypy/doc/draft-jit-outline.txt Log: another try at rewording Modified: pypy/dist/pypy/doc/draft-jit-outline.txt ============================================================================== --- pypy/dist/pypy/doc/draft-jit-outline.txt (original) +++ pypy/dist/pypy/doc/draft-jit-outline.txt Mon Dec 18 17:31:33 2006 @@ -377,14 +377,14 @@ accordingly. This process is called *timeshifting*, because it changes the time at which the graphs are meant to be run. -Keep in mind that the program described as the "source RPython program" -in this document is typically an interpreter - the canonical example is -that it is the whole `PyPy Standard Interpreter`_. This program, -considered as a forest of control flow graphs, implements a typical -interpreter: the flow graphs are meant to execute at run-time, and -directly compute the intended result and side-effects. These are the -flow graphs that we process (and not the application-level program, -which cannot be expressed as low-level flow graphs anyway). +Keep in mind that the program described as the "source RPython +program" in this document is typically an interpreter - the canonical +example is that it is the whole `PyPy Standard Interpreter`_. This +program is meant to execute at run-time, and directly compute the +intended result and side-effects. The translation process transforms it +into a forest of flow graphs. These are the flow graphs that +timeshifting processes (and not the application-level program, which +cannot be expressed as low-level flow graphs anyway). After being timeshifted, the graphs of our interpreter become logically very different: they are no longer intended to be executed at run-time, @@ -392,9 +392,10 @@ effects is to produce residual code. The residual code itself runs "at run-time". -Despite the conceptual difference, though, the timeshifted graphs are -formally close to the original graphs. The rest of this section -describes this timeshifting process in more detail. +Despite the conceptual difference, though, the form (flow of control) +of timeshifted graphs is related and close to the original graphs. +The rest of this section describes this timeshifting process in more +detail. Red and Green Operations From ac at codespeak.net Mon Dec 18 20:24:35 2006 From: ac at codespeak.net (ac at codespeak.net) Date: Mon, 18 Dec 2006 20:24:35 +0100 (CET) Subject: [pypy-svn] r35862 - pypy/dist/pypy/translator/c Message-ID: <20061218192435.BED9010077@code0.codespeak.net> Author: ac Date: Mon Dec 18 20:24:35 2006 New Revision: 35862 Modified: pypy/dist/pypy/translator/c/exceptiontransform.py Log: Make sure the exceptblock is closed and has an empty tuple for operations. Modified: pypy/dist/pypy/translator/c/exceptiontransform.py ============================================================================== --- pypy/dist/pypy/translator/c/exceptiontransform.py (original) +++ pypy/dist/pypy/translator/c/exceptiontransform.py Mon Dec 18 20:24:35 2006 @@ -234,6 +234,9 @@ # attach an except block -- let's hope that nobody uses it graph.exceptblock = Block([Variable('etype'), # exception class Variable('evalue')]) # exception value + graph.exceptblock.operations = () + graph.exceptblock.closeblock() + result = Variable() result.concretetype = lltype.Void block.operations = [SpaceOperation( From arigo at codespeak.net Mon Dec 18 21:15:59 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 18 Dec 2006 21:15:59 +0100 (CET) Subject: [pypy-svn] r35865 - in pypy/dist/pypy: objspace/flow translator translator/backendopt translator/c translator/transformer Message-ID: <20061218201559.1CC1E1007F@code0.codespeak.net> Author: arigo Date: Mon Dec 18 21:15:53 2006 New Revision: 35865 Modified: pypy/dist/pypy/objspace/flow/model.py pypy/dist/pypy/translator/backendopt/inline.py pypy/dist/pypy/translator/backendopt/merge_if_blocks.py pypy/dist/pypy/translator/c/exceptiontransform.py pypy/dist/pypy/translator/simplify.py pypy/dist/pypy/translator/transformer/debug.py Log: Make checkgraph() more strict: it checks that return/except blocks have 'operations == ()' and that exits is always a tuple - but but but, please NEVER write to exits directly, use closeblock() or recloseblock() instead. Modified: pypy/dist/pypy/objspace/flow/model.py ============================================================================== --- pypy/dist/pypy/objspace/flow/model.py (original) +++ pypy/dist/pypy/objspace/flow/model.py Mon Dec 18 21:15:53 2006 @@ -584,11 +584,14 @@ for block, nbargs in exitblocks.items(): assert len(block.inputargs) == nbargs - assert not block.operations - assert not block.exits + assert block.operations == () + assert block.exits == () for block in graph.iterblocks(): assert bool(block.isstartblock) == (block is graph.startblock) + assert type(block.exits) is tuple, ( + "block.exits is a %s (closeblock() or recloseblock() missing?)" + % (type(block.exits).__name__,)) if not block.exits: assert block in exitblocks vars = {} Modified: pypy/dist/pypy/translator/backendopt/inline.py ============================================================================== --- pypy/dist/pypy/translator/backendopt/inline.py (original) +++ pypy/dist/pypy/translator/backendopt/inline.py Mon Dec 18 21:15:53 2006 @@ -237,7 +237,7 @@ newblock = Block(args) self._copied_blocks[block] = newblock newblock.operations = [self.copy_operation(op) for op in block.operations] - newblock.exits = [self.copy_link(link, block) for link in block.exits] + newblock.closeblock(*[self.copy_link(link, block) for link in block.exits]) newblock.exitswitch = self.get_new_name(block.exitswitch) self.search_for_calls(newblock) return newblock @@ -245,7 +245,6 @@ def copy_link(self, link, prevblock): newargs = [self.get_new_name(a) for a in link.args] + self.passon_vars(prevblock) newlink = Link(newargs, self.copy_block(link.target), link.exitcase) - newlink.prevblock = self.copy_block(link.prevblock) newlink.last_exception = self.get_new_name(link.last_exception) newlink.last_exc_value = self.get_new_name(link.last_exc_value) if hasattr(link, 'llexitcase'): @@ -272,9 +271,8 @@ linkargs = ([copiedreturnblock.inputargs[0]] + self.passon_vars(self.graph_to_inline.returnblock)) linkfrominlined = Link(linkargs, afterblock) - linkfrominlined.prevblock = copiedreturnblock copiedreturnblock.exitswitch = None - copiedreturnblock.exits = [linkfrominlined] ## HERE + copiedreturnblock.recloseblock(linkfrominlined) assert copiedreturnblock.exits[0].target == afterblock def rewire_exceptblock(self, afterblock): @@ -358,22 +356,21 @@ l.prevblock = block l.exitcase = True l.llexitcase = True - block.exits.append(l) + block.closeblock(l) if i > 0: l = Link(blocks[-1].inputargs, block) - l.prevblock = blocks[-1] l.exitcase = False l.llexitcase = False - blocks[-1].exits.insert(0, l) + blocks[-1].recloseblock(l, *blocks[-1].exits) blocks.append(block) - blocks[-1].exits = blocks[-1].exits[:1] + blocks[-1].recloseblock(*blocks[-1].exits[:1]) blocks[-1].operations = [] blocks[-1].exitswitch = None blocks[-1].exits[0].exitcase = None del blocks[-1].exits[0].llexitcase linkargs = copiedexceptblock.inputargs - copiedexceptblock.closeblock(Link(linkargs, blocks[0])) ## HERE + copiedexceptblock.recloseblock(Link(linkargs, blocks[0])) ## HERE copiedexceptblock.operations += generate_keepalive(linkargs) @@ -415,7 +412,7 @@ self.rewire_exceptblock(afterblock) if self.exception_guarded: assert afterblock.exits[0].exitcase is None - afterblock.exits = [afterblock.exits[0]] + afterblock.recloseblock(afterblock.exits[0]) afterblock.exitswitch = None self.search_for_calls(afterblock) self.search_for_calls(block) Modified: pypy/dist/pypy/translator/backendopt/merge_if_blocks.py ============================================================================== --- pypy/dist/pypy/translator/backendopt/merge_if_blocks.py (original) +++ pypy/dist/pypy/translator/backendopt/merge_if_blocks.py Mon Dec 18 21:15:53 2006 @@ -33,7 +33,6 @@ default = chain[-1][0].exits[0] default.exitcase = "default" default.llexitcase = None - default.prevblock = firstblock default.args = [get_new_arg(arg) for arg in default.args] for block, case in chain: if case.value in values: @@ -45,10 +44,9 @@ links.append(link) link.exitcase = case.value link.llexitcase = case.value - link.prevblock = firstblock link.args = [get_new_arg(arg) for arg in link.args] links.append(default) - firstblock.exits = links + firstblock.recloseblock(*links) def merge_if_blocks_once(graph): """Convert consecutive blocks that all compare a variable (of Primitive type) Modified: pypy/dist/pypy/translator/c/exceptiontransform.py ============================================================================== --- pypy/dist/pypy/translator/c/exceptiontransform.py (original) +++ pypy/dist/pypy/translator/c/exceptiontransform.py Mon Dec 18 21:15:53 2006 @@ -224,7 +224,7 @@ # " guarding in graph %s" % (lastblock.operations[-1], # graph)) lastblock.exitswitch = None - lastblock.exits = [lastblock.exits[0]] + lastblock.recloseblock(lastblock.exits[0]) lastblock.exits[0].exitcase = None else: self.insert_matching(lastblock, graph) Modified: pypy/dist/pypy/translator/simplify.py ============================================================================== --- pypy/dist/pypy/translator/simplify.py (original) +++ pypy/dist/pypy/translator/simplify.py Mon Dec 18 21:15:53 2006 @@ -203,7 +203,7 @@ link = block.exits[0] ovfblock = link.target check_syntax(ovfblock, block) - block.exits = [link] + block.recloseblock(link) block.exitswitch = None # remove the ovfcheck call from the None target remove_last_op(ovfblock) @@ -284,7 +284,7 @@ link.exitcase = case link.prevblock = block exits.append(link) - block.exits = tuple(preserve + exits) + block.recloseblock(*(preserve + exits)) traverse(visit, graph) @@ -318,7 +318,7 @@ exits.pop() exits.append(link) seen.append(case) - block.exits = tuple(exits) + block.recloseblock(*exits) traverse(visit, graph) @@ -392,7 +392,7 @@ # remove this exit lst = list(block.exits) del lst[i] - block.exits = tuple(lst) + block.recloseblock(*lst) traverse(visit, graph) Modified: pypy/dist/pypy/translator/transformer/debug.py ============================================================================== --- pypy/dist/pypy/translator/transformer/debug.py (original) +++ pypy/dist/pypy/translator/transformer/debug.py Mon Dec 18 21:15:53 2006 @@ -51,6 +51,8 @@ graph.explicit_traceback = True def transform_block(self, graph, block): + if block.operations == (): + return next = [] ann = self.annotator classdef = self.instance_const.concretetype.classdef From arigo at codespeak.net Mon Dec 18 21:19:34 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 18 Dec 2006 21:19:34 +0100 (CET) Subject: [pypy-svn] r35866 - pypy/dist/pypy/lang/js/test Message-ID: <20061218201934.B5B3F1007C@code0.codespeak.net> Author: arigo Date: Mon Dec 18 21:19:33 2006 New Revision: 35866 Modified: pypy/dist/pypy/lang/js/test/test_interp.py Log: Move the skip before the (failing) imports. Modified: pypy/dist/pypy/lang/js/test/test_interp.py ============================================================================== --- pypy/dist/pypy/lang/js/test/test_interp.py (original) +++ pypy/dist/pypy/lang/js/test/test_interp.py Mon Dec 18 21:19:33 2006 @@ -1,3 +1,5 @@ +import py.test +py.test.skip("not finished yet") from pypy.lang.js.astgen import * from pypy.lang.js import interpreter @@ -5,12 +7,10 @@ from pypy.lang.js.interpreter import ThrowException from pypy.lang.js.jsobj import W_Number, W_Object from pypy.lang.js.context import ExecutionContext -import py.test import sys from StringIO import StringIO -py.test.skip("not finished yet") def parse_d(code): return build_interpreter(parse(code)) From ac at codespeak.net Mon Dec 18 22:00:55 2006 From: ac at codespeak.net (ac at codespeak.net) Date: Mon, 18 Dec 2006 22:00:55 +0100 (CET) Subject: [pypy-svn] r35867 - in pypy/dist/pypy: jit/goal rpython/lltypesystem Message-ID: <20061218210055.961411007C@code0.codespeak.net> Author: ac Date: Mon Dec 18 22:00:54 2006 New Revision: 35867 Modified: pypy/dist/pypy/jit/goal/targetjit.py pypy/dist/pypy/rpython/lltypesystem/lloperation.py Log: (arigo, pedronis, arre) Do normal backendopts after timeshifting. Modified: pypy/dist/pypy/jit/goal/targetjit.py ============================================================================== --- pypy/dist/pypy/jit/goal/targetjit.py (original) +++ pypy/dist/pypy/jit/goal/targetjit.py Mon Dec 18 22:00:54 2006 @@ -8,12 +8,21 @@ class __extend__(TranslationDriver): __metaclass__ = extendabletype + def task_prehannotatebackendopt(self): + from pypy.translator.backendopt.all import backend_optimizations + backend_optimizations(self.translator, + inline_threshold=0, + merge_if_blocks=False) + # + task_prehannotatebackendopt = taskdef(task_prehannotatebackendopt, + [TranslationDriver.RTYPE], + "Backendopt before Hint-annotate") def task_hintannotate(self): from pypy.jit.goal import jitstep jitstep.hintannotate(self) # task_hintannotate = taskdef(task_hintannotate, - [TranslationDriver.BACKENDOPT], + ['prehannotatebackendopt'], "Hint-annotate") def task_timeshift(self): @@ -35,8 +44,6 @@ return super(PyPyJITTarget, self).target(driver, args) def handle_config(self, config): - config.translation.backendopt.inline_threshold = 0 - config.translation.backendopt.merge_if_blocks = False config.translation.fork_before = 'hintannotate' def handle_translate_config(self, translateconfig): Modified: pypy/dist/pypy/rpython/lltypesystem/lloperation.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/lloperation.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/lloperation.py Mon Dec 18 22:00:54 2006 @@ -320,7 +320,7 @@ 'direct_fieldptr': LLOp(canfold=True), 'direct_arrayitems': LLOp(canfold=True), 'direct_ptradd': LLOp(canfold=True), - 'cast_opaque_ptr': LLOp(canfold=True), + 'cast_opaque_ptr': LLOp(sideeffects=False), # __________ address operations __________ From santagada at codespeak.net Tue Dec 19 02:05:14 2006 From: santagada at codespeak.net (santagada at codespeak.net) Date: Tue, 19 Dec 2006 02:05:14 +0100 (CET) Subject: [pypy-svn] r35869 - pypy/dist/pypy/lang/js Message-ID: <20061219010514.C748710079@code0.codespeak.net> Author: santagada Date: Tue Dec 19 02:04:55 2006 New Revision: 35869 Modified: pypy/dist/pypy/lang/js/context.py pypy/dist/pypy/lang/js/interpreter.py pypy/dist/pypy/lang/js/jsobj.py pypy/dist/pypy/lang/js/reference.py Log: more work on the context and interpreter, but still non working Modified: pypy/dist/pypy/lang/js/context.py ============================================================================== --- pypy/dist/pypy/lang/js/context.py (original) +++ pypy/dist/pypy/lang/js/context.py Tue Dec 19 02:04:55 2006 @@ -1,3 +1,9 @@ +# encoding: utf-8 + +from copy import copy +from pypy.lang.js.jsobj import w_Undefined, Property +from pypy.lang.js.reference import Reference + class ExecutionContext(object): def __init__(self): @@ -5,21 +11,35 @@ self.this = None self.variable = None self.property = Property('',w_Undefined) #Attribute flags for new vars - - def get_identifier(self, identifier): - """docstring for get_identifier""" - pass - - - - -class GlobalContext(ExecutionContext): - """docstring for GlobalContext""" - def __init__(self, global): - ExecutionContext.__init__() - self.scope.append(global) - self.this = global - self.variable = global + + def push_object(self, obj): + """push object into scope stack""" + self.scope.insert(0, obj) + + def pop_object(self): + """docstring for pop_object""" + return self.scope.pop(0) + def resolve_identifier(self, identifier): + for obj in self.scope: + if obj.HasProperty(identifier): + return Reference(property_name, obj) + + return Reference(property_name) + - +def global_context(global): + ctx = ExecutionContext() + ctx.push_object(global) + ctx.this = global + ctx.variable = global + ctx.property = Property('', w_Undefined, DontDelete=True) + return ctx + +def eval_context(calling_context): + ctx = ExecutionContext() + ctx.scope = copy(calling_context.scope) + ctx.this = calling_context.this + ctx.variable = calling_context.variable + ctx.property = Property('', w_Undefined) + return ctx Modified: pypy/dist/pypy/lang/js/interpreter.py ============================================================================== --- pypy/dist/pypy/lang/js/interpreter.py (original) +++ pypy/dist/pypy/lang/js/interpreter.py Tue Dec 19 02:04:55 2006 @@ -1,5 +1,6 @@ from pypy.lang.js.astgen import * +from pypy.lang.js.jsparser import parse from pypy.lang.js.context import ExecutionContext from pypy.lang.js.jsobj import W_Number, W_String, W_Object from pypy.lang.js.jsobj import w_Undefined, W_Arguments, W_Boolean, NaN @@ -30,11 +31,12 @@ def load_source(self, script_source): """load a source script text to the interpreter""" - pass + temp_dict = parse(script_source) + self.script = from_dict(temp_dict) def run(self): """run the interpreter""" - pass + self.script.Call(self.global_context) Modified: pypy/dist/pypy/lang/js/jsobj.py ============================================================================== --- pypy/dist/pypy/lang/js/jsobj.py (original) +++ pypy/dist/pypy/lang/js/jsobj.py Tue Dec 19 02:04:55 2006 @@ -5,8 +5,7 @@ INFDEF = 1e300 * 1e300 NaN = INFDEF/INFDEF -# TODO: Use an integer for attributes -class Properfty(object): +class Property(object): def __init__(self, name, value, DontDelete=False, ReadOnly=False, DontEnum=False, Internal=False): self.name = name @@ -123,6 +122,13 @@ class W_Arguments(W_Object): pass +class ActivationObject(W_Object): + """The object used on function calls to hold arguments and this""" + def __init__(self): + W_Object.__init__() + self.propdict.pop(P) + + class W_Undefined(W_Root): def __str__(self): return "" Modified: pypy/dist/pypy/lang/js/reference.py ============================================================================== --- pypy/dist/pypy/lang/js/reference.py (original) +++ pypy/dist/pypy/lang/js/reference.py Tue Dec 19 02:04:55 2006 @@ -1,10 +1,4 @@ -#!/usr/bin/env python # encoding: utf-8 -""" -reference.py - -Created by Leonardo Santagada on 2006-12-16. -""" class Reference(object): """Reference Type""" @@ -19,10 +13,10 @@ raise ReferenceError return v.baseobject.get(v.propertyname) -def put_value(v, w): +def put_value(v, w, context): if not type(v, Reference): raise ReferenceError base = v.baseobject if v.baseobject is None: - base = get_global() #gets the global object of js + base = context.scope[-1] base.put(v.propertyname, w) \ No newline at end of file From mwh at codespeak.net Tue Dec 19 09:31:26 2006 From: mwh at codespeak.net (mwh at codespeak.net) Date: Tue, 19 Dec 2006 09:31:26 +0100 (CET) Subject: [pypy-svn] r35872 - pypy/dist/pypy/translator/goal Message-ID: <20061219083126.78E4E1007F@code0.codespeak.net> Author: mwh Date: Tue Dec 19 09:31:25 2006 New Revision: 35872 Modified: pypy/dist/pypy/translator/goal/bench-unix.py Log: band-aid to stop pypy-cli's moving around halting benchmarks Modified: pypy/dist/pypy/translator/goal/bench-unix.py ============================================================================== --- pypy/dist/pypy/translator/goal/bench-unix.py (original) +++ pypy/dist/pypy/translator/goal/bench-unix.py Tue Dec 19 09:31:25 2006 @@ -148,7 +148,10 @@ if 'pypy-cli' in exename: dirname = exename + '-data' codesize = 'N/A' - exesize = os.path.getsize(os.path.join(dirname, 'main.exe')) + try: + exesize = os.path.getsize(os.path.join(dirname, 'main.exe')) + except OSError: + exesize = 'XXX'' else: codesize = os.popen('size "%s" | tail -n1 | cut -f1'%(exename,)).read().strip() exesize = os.path.getsize(exe) From mwh at codespeak.net Tue Dec 19 09:43:03 2006 From: mwh at codespeak.net (mwh at codespeak.net) Date: Tue, 19 Dec 2006 09:43:03 +0100 (CET) Subject: [pypy-svn] r35873 - pypy/dist/pypy/translator/goal Message-ID: <20061219084303.35CD21007F@code0.codespeak.net> Author: mwh Date: Tue Dec 19 09:43:02 2006 New Revision: 35873 Modified: pypy/dist/pypy/translator/goal/bench-unix.py Log: oops Modified: pypy/dist/pypy/translator/goal/bench-unix.py ============================================================================== --- pypy/dist/pypy/translator/goal/bench-unix.py (original) +++ pypy/dist/pypy/translator/goal/bench-unix.py Tue Dec 19 09:43:02 2006 @@ -151,7 +151,7 @@ try: exesize = os.path.getsize(os.path.join(dirname, 'main.exe')) except OSError: - exesize = 'XXX'' + exesize = 'XXX' else: codesize = os.popen('size "%s" | tail -n1 | cut -f1'%(exename,)).read().strip() exesize = os.path.getsize(exe) From pedronis at codespeak.net Tue Dec 19 09:51:45 2006 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Tue, 19 Dec 2006 09:51:45 +0100 (CET) Subject: [pypy-svn] r35874 - in pypy/dist/pypy/rpython: . lltypesystem Message-ID: <20061219085145.5825D10086@code0.codespeak.net> Author: pedronis Date: Tue Dec 19 09:51:43 2006 New Revision: 35874 Modified: pypy/dist/pypy/rpython/llinterp.py pypy/dist/pypy/rpython/lltypesystem/opimpl.py Log: oops, move impl to match lloperation decl Modified: pypy/dist/pypy/rpython/llinterp.py ============================================================================== --- pypy/dist/pypy/rpython/llinterp.py (original) +++ pypy/dist/pypy/rpython/llinterp.py Tue Dec 19 09:51:43 2006 @@ -646,6 +646,10 @@ checkptr(ptr1) return lltype.cast_ptr_to_int(ptr1) + def op_cast_opaque_ptr(self, RESTYPE, obj): + checkptr(obj) + return lltype.cast_opaque_ptr(RESTYPE, obj) + op_cast_opaque_ptr.need_result_type = True def op_gc__collect(self): import gc Modified: pypy/dist/pypy/rpython/lltypesystem/opimpl.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/opimpl.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/opimpl.py Tue Dec 19 09:51:43 2006 @@ -243,11 +243,6 @@ return lltype.cast_pointer(RESTYPE, obj) op_cast_pointer.need_result_type = True -def op_cast_opaque_ptr(RESTYPE, obj): - checkptr(obj) - return lltype.cast_opaque_ptr(RESTYPE, obj) -op_cast_opaque_ptr.need_result_type = True - def op_cast_ptr_to_weakadr(ptr): checkptr(ptr) return llmemory.cast_ptr_to_weakadr(ptr) From auc at codespeak.net Tue Dec 19 10:40:37 2006 From: auc at codespeak.net (auc at codespeak.net) Date: Tue, 19 Dec 2006 10:40:37 +0100 (CET) Subject: [pypy-svn] r35875 - in pypy/dist/pypy/objspace: cclp cclp/constraint test Message-ID: <20061219094037.72EC410086@code0.codespeak.net> Author: auc Date: Tue Dec 19 10:40:32 2006 New Revision: 35875 Modified: pypy/dist/pypy/objspace/cclp/constraint/domain.py pypy/dist/pypy/objspace/cclp/scheduler.py pypy/dist/pypy/objspace/cclp/space.py pypy/dist/pypy/objspace/cclp/thunk.py pypy/dist/pypy/objspace/cclp/types.py pypy/dist/pypy/objspace/test/test_logicobjspace.py Log: current state of the (non-cloning) cloning stuff, better error checking bits wrt applevel Modified: pypy/dist/pypy/objspace/cclp/constraint/domain.py ============================================================================== --- pypy/dist/pypy/objspace/cclp/constraint/domain.py (original) +++ pypy/dist/pypy/objspace/cclp/constraint/domain.py Tue Dec 19 10:40:32 2006 @@ -138,8 +138,6 @@ def intersection(space, w_fd1, w_fd2): - assert isinstance(w_fd1, W_FiniteDomain) - assert isinstance(w_fd2, W_FiniteDomain) return space.intersection(w_fd1, w_fd2) app_intersection = gateway.interp2app(intersection) Modified: pypy/dist/pypy/objspace/cclp/scheduler.py ============================================================================== --- pypy/dist/pypy/objspace/cclp/scheduler.py (original) +++ pypy/dist/pypy/objspace/cclp/scheduler.py Tue Dec 19 10:40:32 2006 @@ -41,11 +41,18 @@ group._prev = l group._next = r + def schedule(self): + running = self._head to_be_run = self._select_next() assert isinstance(to_be_run, W_ThreadGroupScheduler), "type error" #w(".. SWITCHING (spaces)", str(id(get_current_cspace(self.space))), "=>", str(id(to_be_run))) self._switch_count += 1 + if to_be_run != running: + if running._pool is not None: + running.goodbye() + if to_be_run._pool is not None: + to_be_run.hello() to_be_run.schedule() def _select_next(self): @@ -230,10 +237,12 @@ #-- Thread Group scheduler -------------------------------------- + class W_ThreadGroupScheduler(baseobjspace.Wrappable): def __init__(self, space): self.space = space + self._pool = None self._switch_count = 0 self._traced = {} # thread -> vars self.thread_count = 1 @@ -259,6 +268,18 @@ thread._prev = l thread._next = r + def hello(self): + self._pool.hello_local_pool() + + def goodbye(self): + self._pool.goodbye_local_pool() + + def register_var(self, var): + space = self.space + raise OperationError(space.w_AssertionError, + space.wrap('You cannot create a constraint variable ' + 'in the top-level computation space.')) + def is_blocked(self): return self.thread_count == self.blocked_count Modified: pypy/dist/pypy/objspace/cclp/space.py ============================================================================== --- pypy/dist/pypy/objspace/cclp/space.py (original) +++ pypy/dist/pypy/objspace/cclp/space.py Tue Dec 19 10:40:32 2006 @@ -15,13 +15,11 @@ from pypy.objspace.cclp.global_state import sched from pypy.objspace.cclp.variable import newvar from pypy.objspace.cclp.types import ConsistencyError, Solution, W_Var, \ - W_CVar, W_AbstractDomain, W_AbstractDistributor + W_CVar, W_AbstractDomain, W_AbstractDistributor, Pool from pypy.objspace.cclp.interp_var import interp_bind, interp_free from pypy.objspace.cclp.constraint.distributor import distribute from pypy.objspace.cclp.scheduler import W_ThreadGroupScheduler -from pypy.rlib.rgc import gc_swap_pool, gc_clone - def newspace(space, w_callable, __args__): "application level creation of a new computation space" args = __args__.normalize() @@ -39,81 +37,66 @@ def choose(space, w_n): - assert isinstance(w_n, W_IntObject) + if not isinstance(w_n, W_IntObject): + raise OperationError(space.w_TypeError, + space.wrap('Choose only accepts an integer.')) n = space.int_w(w_n) + # XXX sanity check for 1 <= n <= last_choice cspace = get_current_cspace(space) - if cspace is not None: - assert isinstance(cspace, W_CSpace) - try: - return cspace.choose(w_n.intval) - except ConsistencyError: - raise OperationError(space.w_ConsistencyError, - space.wrap("the space is failed")) - raise OperationError(space.w_RuntimeError, - space.wrap("choose is forbidden from the top-level space")) + if not isinstance(cspace, W_CSpace): + raise OperationError(space.w_TypeError, + space.wrap('Choose does not work from within ' + 'the top-level computatoin space.')) + try: + return cspace.choose(n) + except ConsistencyError: + raise OperationError(space.w_ConsistencyError, + space.wrap("the space is failed")) app_choose = gateway.interp2app(choose) - from pypy.objspace.cclp.constraint import constraint def tell(space, w_constraint): - assert isinstance(w_constraint, constraint.W_AbstractConstraint) + if not isinstance(w_constraint, constraint.W_AbstractConstraint): + raise OperationError(space.w_TypeError, + space.wrap('Tell only accepts object of ' + '(sub-)types Constraint.')) get_current_cspace(space).tell(w_constraint) app_tell = gateway.interp2app(tell) -if not we_are_translated(): - def fresh_distributor(space, w_dist): - cspace = w_dist._cspace - while w_dist.distributable(): - choice = cspace.choose(w_dist.fanout()) - w_dist.w_distribute(choice) - app_fresh_distributor = gateway.interp2app(fresh_distributor) - class W_CSpace(W_ThreadGroupScheduler): - local_pool = None def __init__(self, space, dist_thread): W_ThreadGroupScheduler.__init__(self, space) dist_thread._cspace = self self._init_head(dist_thread) self._next = self._prev = self + self._pool = Pool(self) sched.uler.add_new_group(self) - self.distributor = None # dist instance != thread - self._container = None # thread that 'contains' us # choice mgmt self._choice = newvar(space) self._committed = newvar(space) # status, merging self._solution = newvar(space) - self._finished = newvar(space) self._failed = False + self._merged = False + self._finished = newvar(space) # constraint store ... self._store = {} # name -> var - if not we_are_translated(): - self._constraints = [] def register_var(self, cvar): self._store[cvar.name] = cvar def w_clone(self): - if we_are_translated(): - w("<> cloning the space") - if self.local_pool is None: - self.local_pool = gc_swap_pool(gc_swap_pool(None)) - new_cspace, new_cspace.local_pool = gc_clone(self, self.local_pool) - w("<> add cloned cspace to new group") - assert isinstance(new_cspace, W_CSpace) - new_cspace._next = new_cspace._prev = new_cspace - sched.uler.add_new_group(new_cspace) - w("<> returning clone ") - return new_cspace - else: - raise NotImplementedError - + clone = self._pool.clone() + return self.space.wrap(clone.cspace) def w_ask(self): + if not interp_free(self._finished): + raise OperationError(self.space.w_RuntimeError, + self.space.wrap("space is finished")) self.wait_stable() self.space.wait(self._choice) choice = self._choice.w_bound_to @@ -123,6 +106,9 @@ return choice def choose(self, n): + if not interp_free(self._finished): + raise OperationError(self.space.w_RuntimeError, + self.space.wrap("space is finished")) # solver probably asks assert n > 1 self.wait_stable() @@ -138,6 +124,9 @@ return committed def w_commit(self, w_n): + if not interp_free(self._finished): + raise OperationError(self.space.w_RuntimeError, + self.space.wrap("space is finished")) assert isinstance(w_n, W_IntObject) n = w_n.intval assert interp_free(self._committed) @@ -152,9 +141,6 @@ w_coro._cspace = self thunk = PropagatorThunk(space, w_constraint, w_coro) w_coro.bind(thunk) - if not we_are_translated(): - w("PROPAGATOR in thread", str(id(w_coro))) - self._constraints.append(w_constraint) self.add_new_thread(w_coro) def fail(self): @@ -167,6 +153,10 @@ def w_merge(self): # let's bind the solution variables + if self._merged: + raise OperationError(self.space.w_RuntimeError, + self.space.wrap("space is already merged")) + self._merged = True sol = self._solution.w_bound_to if isinstance(sol, W_ListObject): self._bind_solution_variables(sol.wrappeditems) @@ -191,10 +181,7 @@ def contains_cvar(lst): - for elt in lst: - if isinstance(elt, W_CVar): - return True - return False + return isinstance(lst[0], W_CVar) W_CSpace.typedef = typedef.TypeDef("W_CSpace", Modified: pypy/dist/pypy/objspace/cclp/thunk.py ============================================================================== --- pypy/dist/pypy/objspace/cclp/thunk.py (original) +++ pypy/dist/pypy/objspace/cclp/thunk.py Tue Dec 19 10:40:32 2006 @@ -108,7 +108,7 @@ outcome = sol.w_bound_to if not (isinstance(outcome, W_ListObject) or \ isinstance(outcome, W_TupleObject)): - w("WARNING: return value type of the script was not a list or tuple, we fail ...") + w("WARNING: return value type of the script was not a list or tuple, we fail the space.") cspace.fail() return assert interp_free(cspace._choice) Modified: pypy/dist/pypy/objspace/cclp/types.py ============================================================================== --- pypy/dist/pypy/objspace/cclp/types.py (original) +++ pypy/dist/pypy/objspace/cclp/types.py Tue Dec 19 10:40:32 2006 @@ -2,6 +2,10 @@ from pypy.interpreter.error import OperationError from pypy.objspace.cclp.misc import w, AppCoroutine, get_current_cspace +from pypy.objspace.cclp.global_state import sched + +from pypy.rlib.rgc import gc_swap_pool, gc_clone +from pypy.rlib.objectmodel import we_are_translated W_Root = baseobjspace.W_Root @@ -42,11 +46,7 @@ self.w_dom = w_dom self.name = space.str_w(w_name) self.w_nam = w_name - cspace = get_current_cspace(space) - if cspace is None: - w("-- WARNING : you are instanciating a constraint var in the top-level space") - else: - cspace.register_var(self) + get_current_cspace(space).register_var(self) def copy(self, space): return W_CVar(space, self.w_dom.copy(), self.w_nam) @@ -124,6 +124,49 @@ W_AbstractDistributor.typedef = typedef.TypeDef("W_AbstractDistributor") +#-- Pool -------------------------------------------------- + +class Pool: + local_pool = None + + def __init__(self, cspace=None): + self.cspace = cspace + + def hello_local_pool(self): + if we_are_translated(): + w('hello_local_pool') + self.saved_pool = gc_swap_pool(self.local_pool) + + def goodbye_local_pool(self): + if we_are_translated(): + w('goodbye_local_pool') + self.local_pool = gc_swap_pool(self.saved_pool) + self.saved_pool = None + + def clone(self): + copy = Pool() + self.clone_into(copy) + return copy + + def clone_into(self, copy, extradata=None): + # blindly copied from interp_clonable + # all we need is love, after all ... + if not we_are_translated(): + raise NotImplementedError + # cannot gc_clone() directly self, because it is not in its own + # local_pool. Moreover, it has a __del__, which cloning doesn't + # support properly at the moment. + # the hello/goodbye pair has two purposes: it forces + # self.local_pool to be computed even if it was None up to now, + # and it puts the 'data' tuple in the correct pool to be cloned. + self.hello_local_pool() + data = (self.cspace, extradata) + self.goodbye_local_pool() + # clone! + data, copy.local_pool = gc_clone(data, self.local_pool) + copy.cspace, extradata = data + return extradata + #-- Misc --------------------------------------------------- Modified: pypy/dist/pypy/objspace/test/test_logicobjspace.py ============================================================================== --- pypy/dist/pypy/objspace/test/test_logicobjspace.py (original) +++ pypy/dist/pypy/objspace/test/test_logicobjspace.py Tue Dec 19 10:40:32 2006 @@ -764,6 +764,7 @@ break if status: unify(Sol, spc.merge()) + raises(AssertionError, spc.merge) else: unify(Sol, False) From ericvrp at codespeak.net Tue Dec 19 11:47:38 2006 From: ericvrp at codespeak.net (ericvrp at codespeak.net) Date: Tue, 19 Dec 2006 11:47:38 +0100 (CET) Subject: [pypy-svn] r35876 - pypy/extradoc/sprintinfo/leysin-winter-2007 Message-ID: <20061219104738.268EF10078@code0.codespeak.net> Author: ericvrp Date: Tue Dec 19 11:47:36 2006 New Revision: 35876 Modified: pypy/extradoc/sprintinfo/leysin-winter-2007/people.txt Log: Added myself to the Leysin sprint, dates not fixed. Modified: pypy/extradoc/sprintinfo/leysin-winter-2007/people.txt ============================================================================== --- pypy/extradoc/sprintinfo/leysin-winter-2007/people.txt (original) +++ pypy/extradoc/sprintinfo/leysin-winter-2007/people.txt Tue Dec 19 11:47:36 2006 @@ -20,6 +20,7 @@ Niko Matsakis 9th-14th Ermina Antonio Cuni 7th-15th Ermina Maciej Fijalkowski 5th?-17th? Ermina +Eric van Riet Paap 10th?-14th? Ermina ==================== ============== ===================== People on the following list were present at previous sprints: @@ -43,7 +44,6 @@ Bert Freudenberg ? ? Laura Creighton ? ? Beatrice Duering ? ? -Eric van Riet Paap ? ? Carl Friedrich Bolz ? ? Richard Emslie ? ? Johan Hahn ? ? From arigo at codespeak.net Tue Dec 19 12:36:32 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 19 Dec 2006 12:36:32 +0100 (CET) Subject: [pypy-svn] r35878 - pypy/dist/pypy/jit/codegen/i386 Message-ID: <20061219113632.DB67010072@code0.codespeak.net> Author: arigo Date: Tue Dec 19 12:36:31 2006 New Revision: 35878 Modified: pypy/dist/pypy/jit/codegen/i386/codebuf.py Log: When compiling, reset the machine_code_dumper global instance to its default state. Modified: pypy/dist/pypy/jit/codegen/i386/codebuf.py ============================================================================== --- pypy/dist/pypy/jit/codegen/i386/codebuf.py (original) +++ pypy/dist/pypy/jit/codegen/i386/codebuf.py Tue Dec 19 12:36:31 2006 @@ -63,6 +63,13 @@ log_fd = -1 sys_executable = None + def _freeze_(self): + # reset the machine_code_dumper global instance to its default state + if self.log_fd >= 0: + os.close(self.log_fd) + self.__dict__.clear() + return False + def open(self): if self.log_fd < 0: # check the environment for a file name From pedronis at codespeak.net Tue Dec 19 13:28:35 2006 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Tue, 19 Dec 2006 13:28:35 +0100 (CET) Subject: [pypy-svn] r35879 - pypy/extradoc/planning/secprototype Message-ID: <20061219122835.9F75F10079@code0.codespeak.net> Author: pedronis Date: Tue Dec 19 13:28:34 2006 New Revision: 35879 Added: pypy/extradoc/planning/secprototype/talk.txt (contents, props changed) Log: (arigo, pedronis) some draft contents and open questions Added: pypy/extradoc/planning/secprototype/talk.txt ============================================================================== --- (empty file) +++ pypy/extradoc/planning/secprototype/talk.txt Tue Dec 19 13:28:34 2006 @@ -0,0 +1,32 @@ + +* PyPy architecture + +* space proxying and operation control: + + - thunk + - taint + +* easy to add new bytecode operations + +* potentially we should be able to implement a large range + of security polices + +* our jit architecture should allow to remove some checks overhead + +------------------------------------------------------------ + + +* open design issues: + + - pure dynamic implementation: what kind of rules to avoid control + flow information leaks + + - label restriction propagation + - label restriction enforcing + - how to attach "credentials" to executed code + +- simple labels principals model (for prototyping) + + + + From arigo at codespeak.net Tue Dec 19 13:36:00 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 19 Dec 2006 13:36:00 +0100 (CET) Subject: [pypy-svn] r35880 - pypy/dist/pypy/doc Message-ID: <20061219123600.21BF21007C@code0.codespeak.net> Author: arigo Date: Tue Dec 19 13:35:59 2006 New Revision: 35880 Modified: pypy/dist/pypy/doc/stackless.txt Log: Mention infinite recursion as an app-level feature of stackless pypy-c (thanks Lenard). Modified: pypy/dist/pypy/doc/stackless.txt ============================================================================== --- pypy/dist/pypy/doc/stackless.txt (original) +++ pypy/dist/pypy/doc/stackless.txt Tue Dec 19 13:35:59 2006 @@ -6,9 +6,9 @@ ================ PyPy can expose to its user language features similar to the ones -present in `Stackless Python`_: the ability to write code in a massively -concurrent style. It actually exposes three different paradigms to -choose from: +present in `Stackless Python`_: **no recursion depth limit**, and the +ability to write code in a **massively concurrent style**. It actually +exposes three different paradigms to choose from: * `Tasklets and channels`_; @@ -66,6 +66,17 @@ paradigm. This is discussed in the Composability_ section below. +Infinite recursion +++++++++++++++++++ + +Any stackless PyPy executable natively supports recursion that is only +limited by the available memory. As in normal Python, though, there is +an initial recursion limit (which is 5000 in all pypy-c's, and 1000 in +CPython). It can be changed with ``sys.setrecursionlimit()``. With a +stackless PyPy, any value is acceptable - use ``sys.maxint`` for +unlimited. + + Coroutines ++++++++++ From arigo at codespeak.net Tue Dec 19 13:57:53 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 19 Dec 2006 13:57:53 +0100 (CET) Subject: [pypy-svn] r35881 - pypy/dist/pypy/jit/codegen/i386/test Message-ID: <20061219125753.E724410072@code0.codespeak.net> Author: arigo Date: Tue Dec 19 13:57:50 2006 New Revision: 35881 Modified: pypy/dist/pypy/jit/codegen/i386/test/test_genc_tlc.py Log: Fix comment (for py.test -k completion). Modified: pypy/dist/pypy/jit/codegen/i386/test/test_genc_tlc.py ============================================================================== --- pypy/dist/pypy/jit/codegen/i386/test/test_genc_tlc.py (original) +++ pypy/dist/pypy/jit/codegen/i386/test/test_genc_tlc.py Tue Dec 19 13:57:50 2006 @@ -7,6 +7,6 @@ test_tlc.TestTLC): # for the individual tests see - # ====> ../../../timeshifter/test/test_tl.py + # ====> ../../../timeshifter/test/test_tlc.py pass From pedronis at codespeak.net Tue Dec 19 13:57:56 2006 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Tue, 19 Dec 2006 13:57:56 +0100 (CET) Subject: [pypy-svn] r35882 - pypy/dist/pypy/doc Message-ID: <20061219125756.EA6B410091@code0.codespeak.net> Author: pedronis Date: Tue Dec 19 13:57:51 2006 New Revision: 35882 Modified: pypy/dist/pypy/doc/draft-jit-outline.txt pypy/dist/pypy/doc/jit.txt Log: move the short bit about backends to the new jit documentation Modified: pypy/dist/pypy/doc/draft-jit-outline.txt ============================================================================== --- pypy/dist/pypy/doc/draft-jit-outline.txt (original) +++ pypy/dist/pypy/doc/draft-jit-outline.txt Tue Dec 19 13:57:51 2006 @@ -652,13 +652,16 @@ Backends ==================== -... +The compilers produced by the timeshifter are linked with one of our +backends, which are written by hand in RPython. We currently have a +backend for producing IA32/i386 machine code in memory, PowerPC machine +code in memory, or (for testing) further low-level control flow graphs. The Backend interface ----------------------- -... - +The interface (which is not yet completely stable) is documented in +`pypy/jit/codegen/model.py`_. .. _VMC: http://codespeak.net/svn/pypy/extradoc/talk/dls2006/pypy-vm-construction.pdf Modified: pypy/dist/pypy/doc/jit.txt ============================================================================== --- pypy/dist/pypy/doc/jit.txt (original) +++ pypy/dist/pypy/doc/jit.txt Tue Dec 19 13:57:51 2006 @@ -243,12 +243,5 @@ Backends ---------------- -The compilers produced by the timeshifter are linked with one of our -backends, which are written by hand in RPython. We currently have a -backend for producing IA32/i386 machine code in memory, PowerPC machine -code in memory, or (for testing) further low-level control flow graphs. - -The interface is documented in `pypy/jit/codegen/model.py`_. - .. include:: _ref.txt From mwh at codespeak.net Tue Dec 19 14:30:10 2006 From: mwh at codespeak.net (mwh at codespeak.net) Date: Tue, 19 Dec 2006 14:30:10 +0100 (CET) Subject: [pypy-svn] r35883 - pypy/branch/builtin-call-speedup-2 Message-ID: <20061219133010.9AB7310078@code0.codespeak.net> Author: mwh Date: Tue Dec 19 14:30:05 2006 New Revision: 35883 Added: pypy/branch/builtin-call-speedup-2/ - copied from r35882, pypy/dist/ Log: branch to builtin-call-speedup-2 From arigo at codespeak.net Tue Dec 19 14:34:20 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 19 Dec 2006 14:34:20 +0100 (CET) Subject: [pypy-svn] r35884 - pypy/dist/pypy/jit/codegen/i386 Message-ID: <20061219133420.BBBAA10078@code0.codespeak.net> Author: arigo Date: Tue Dec 19 14:34:18 2006 New Revision: 35884 Modified: pypy/dist/pypy/jit/codegen/i386/viewcode.py Log: Fixes in the machine code viewer. Code written later overwrites earlier code at the same location. Modified: pypy/dist/pypy/jit/codegen/i386/viewcode.py ============================================================================== --- pypy/dist/pypy/jit/codegen/i386/viewcode.py (original) +++ pypy/dist/pypy/jit/codegen/i386/viewcode.py Tue Dec 19 14:34:18 2006 @@ -82,18 +82,25 @@ self.addr = addr self.data = data + def __repr__(self): + return '' % (hex(self.addr), len(self.data)) + def touches(self, other): return (self .addr < other.addr + len(other.data) and other.addr < self .addr + len(self.data)) - def update(self, other): + def update_from_old(self, other): if other.addr < self.addr: delta = self.addr - other.addr + assert delta <= len(other.data) self.addr -= delta - self.data = '\x00'*delta + self.data - ofs1 = other.addr - self.addr - ofs2 = ofs1 + len(other.data) - self.data = self.data[:ofs1] + other.data + self.data[ofs2:] + self.data = other.data[:delta] + self.data + self_end = self .addr + len(self .data) + other_end = other.addr + len(other.data) + if other_end > self_end: + extra = other_end - self_end + assert extra <= len(other.data) + self.data += other.data[-extra:] def cmpop(op): def _cmp(self, other): @@ -170,11 +177,11 @@ i = bisect_left(self.ranges, coderange) j = i while i>0 and coderange.touches(self.ranges[i-1]): - coderange.update(self.ranges[i-1]) + coderange.update_from_old(self.ranges[i-1]) i -= 1 while j Author: arigo Date: Tue Dec 19 14:53:16 2006 New Revision: 35886 Modified: pypy/dist/pypy/jit/codegen/i386/codebuf.py pypy/dist/pypy/jit/codegen/i386/rgenop.py Log: An optimization that avoids the 'JMP right_to_the_next_insn' that are now common. Modified: pypy/dist/pypy/jit/codegen/i386/codebuf.py ============================================================================== --- pypy/dist/pypy/jit/codegen/i386/codebuf.py (original) +++ pypy/dist/pypy/jit/codegen/i386/codebuf.py Tue Dec 19 14:53:16 2006 @@ -41,6 +41,11 @@ baseaddr = cast(self._data, c_void_p).value return baseaddr + self._pos + def seekback(self, count): + pos = self._pos - count + self._pos = pos + self._last_dump_start = pos + def execute(self, arg1, arg2): # XXX old testing stuff fnptr = cast(self._data, binaryfn) 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 Tue Dec 19 14:53:16 2006 @@ -241,15 +241,32 @@ come_froms = self._pending_come_from self._pending_come_from = None for start, (end, insn) in come_froms.iteritems(): - mc = self.rgenop.InMemoryCodeBuilder(start, end) - self._emit_come_from(mc, insn, self.start) - mc.done() + if end == self.start: + # there was a pending JMP just before self.start, + # so we can as well overwrite the JMP and start writing + # code directly there + self.mc.seekback(end - start) + self.start = start + break + for start, (end, insn) in come_froms.iteritems(): + if start != self.start: + mc = self.rgenop.InMemoryCodeBuilder(start, end) + self._emit_come_from(mc, insn, self.start) + mc.done() else: # We have been paused and are being opened again. - # Patch the jump at the end of the previous codeblock. - mc = self.rgenop.InMemoryCodeBuilder(*self.tail) - mc.JMP(rel32(self.mc.tell())) - mc.done() + # Is the new codeblock immediately after the previous one? + prevstart, prevend = self.tail + curpos = self.mc.tell() + if prevend == curpos: + # Yes. We can overwrite the JMP and just continue writing + # code directly there + self.mc.seekback(prevend - prevstart) + else: + # No. Patch the jump at the end of the previous codeblock. + mc = self.rgenop.InMemoryCodeBuilder(prevstart, prevend) + mc.JMP(rel32(curpos)) + mc.done() def pause(self): if self.mc is None: From pedronis at codespeak.net Tue Dec 19 15:08:18 2006 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Tue, 19 Dec 2006 15:08:18 +0100 (CET) Subject: [pypy-svn] r35887 - in pypy/dist/pypy/doc: . discussion Message-ID: <20061219140818.A102A10078@code0.codespeak.net> Author: pedronis Date: Tue Dec 19 15:08:15 2006 New Revision: 35887 Added: pypy/dist/pypy/doc/discussion/jit-spring06-thinking.txt - copied unchanged from r35882, pypy/dist/pypy/doc/jit.txt pypy/dist/pypy/doc/jit.txt - copied unchanged from r35884, pypy/dist/pypy/doc/draft-jit-outline.txt Removed: pypy/dist/pypy/doc/draft-jit-outline.txt Log: rename draft to jit.txt From pedronis at codespeak.net Tue Dec 19 15:15:07 2006 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Tue, 19 Dec 2006 15:15:07 +0100 (CET) Subject: [pypy-svn] r35889 - pypy/dist/pypy/doc Message-ID: <20061219141507.6835F10079@code0.codespeak.net> Author: pedronis Date: Tue Dec 19 15:14:54 2006 New Revision: 35889 Modified: pypy/dist/pypy/doc/jit.txt Log: missing anchor Modified: pypy/dist/pypy/doc/jit.txt ============================================================================== --- pypy/dist/pypy/doc/jit.txt (original) +++ pypy/dist/pypy/doc/jit.txt Tue Dec 19 15:14:54 2006 @@ -146,6 +146,7 @@ * *Red* variables contain values that are not known until run-time - e.g. ``y``. +.. _`hint annotator`: Binding-time analysis ========================================= From pedronis at codespeak.net Tue Dec 19 15:19:31 2006 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Tue, 19 Dec 2006 15:19:31 +0100 (CET) Subject: [pypy-svn] r35890 - pypy/dist/pypy/doc/discussion Message-ID: <20061219141931.9BC371007C@code0.codespeak.net> Author: pedronis Date: Tue Dec 19 15:19:25 2006 New Revision: 35890 Modified: pypy/dist/pypy/doc/discussion/jit-spring06-thinking.txt Log: bah Modified: pypy/dist/pypy/doc/discussion/jit-spring06-thinking.txt ============================================================================== --- pypy/dist/pypy/doc/discussion/jit-spring06-thinking.txt (original) +++ pypy/dist/pypy/doc/discussion/jit-spring06-thinking.txt Tue Dec 19 15:19:25 2006 @@ -6,11 +6,6 @@ Warning: These are just a few notes quickly thrown together, to be clarified and expanded. -For now we are working on the parallel document `draft-jit-outline`_. - -.. _`draft-jit-outline`: draft-jit-outline.html - - Draft ========================= @@ -244,4 +239,4 @@ ---------------- -.. include:: _ref.txt +.. include:: ../_ref.txt From mwh at codespeak.net Tue Dec 19 15:37:10 2006 From: mwh at codespeak.net (mwh at codespeak.net) Date: Tue, 19 Dec 2006 15:37:10 +0100 (CET) Subject: [pypy-svn] r35891 - in pypy/branch/builtin-call-speedup-2: lib-python/modified-2.4.1 pypy/config pypy/interpreter pypy/interpreter/astcompiler pypy/module/__builtin__ pypy/module/__builtin__/test pypy/objspace/std Message-ID: <20061219143710.340A11007C@code0.codespeak.net> Author: mwh Date: Tue Dec 19 15:37:02 2006 New Revision: 35891 Modified: pypy/branch/builtin-call-speedup-2/lib-python/modified-2.4.1/opcode.py pypy/branch/builtin-call-speedup-2/pypy/config/pypyoption.py pypy/branch/builtin-call-speedup-2/pypy/interpreter/astcompiler/pycodegen.py pypy/branch/builtin-call-speedup-2/pypy/interpreter/module.py pypy/branch/builtin-call-speedup-2/pypy/interpreter/pyopcode.py pypy/branch/builtin-call-speedup-2/pypy/module/__builtin__/__init__.py pypy/branch/builtin-call-speedup-2/pypy/module/__builtin__/test/test_builtin.py pypy/branch/builtin-call-speedup-2/pypy/objspace/std/dictmultiobject.py pypy/branch/builtin-call-speedup-2/pypy/objspace/std/objspace.py Log: merge forward. seems to work, not done a translation yet tho. Modified: pypy/branch/builtin-call-speedup-2/lib-python/modified-2.4.1/opcode.py ============================================================================== --- pypy/branch/builtin-call-speedup-2/lib-python/modified-2.4.1/opcode.py (original) +++ pypy/branch/builtin-call-speedup-2/lib-python/modified-2.4.1/opcode.py Tue Dec 19 15:37:02 2006 @@ -187,4 +187,7 @@ def_op('EXTENDED_ARG', 143) EXTENDED_ARG = 143 +# pypy modification, experimental bytecode +def_op('CALL_LIKELY_BUILTIN', 144) # #args + (#kwargs << 8) + del def_op, name_op, jrel_op, jabs_op Modified: pypy/branch/builtin-call-speedup-2/pypy/config/pypyoption.py ============================================================================== --- pypy/branch/builtin-call-speedup-2/pypy/config/pypyoption.py (original) +++ pypy/branch/builtin-call-speedup-2/pypy/config/pypyoption.py Tue Dec 19 15:37:02 2006 @@ -38,6 +38,10 @@ cmdline='--compiler'), OptionDescription("opcodes", "opcodes to enable in the interpreter", [ + BoolOption("CALL_LIKELY_BUILTIN", "emit a special bytecode for likely calls to builtin functions", + default=False, + requires=[("objspace.usepycfiles", False), + ("objspace.std.withmultidict", True)]) ]), BoolOption("nofaking", "disallow faking in the object space", Modified: pypy/branch/builtin-call-speedup-2/pypy/interpreter/astcompiler/pycodegen.py ============================================================================== --- pypy/branch/builtin-call-speedup-2/pypy/interpreter/astcompiler/pycodegen.py (original) +++ pypy/branch/builtin-call-speedup-2/pypy/interpreter/astcompiler/pycodegen.py Tue Dec 19 15:37:02 2006 @@ -30,6 +30,8 @@ TRY_FINALLY = 3 END_FINALLY = 4 +from pypy.module.__builtin__.__init__ import BUILTIN_TO_INDEX + def compileFile(filename, display=0): f = open(filename, 'U') buf = f.read() @@ -1005,6 +1007,8 @@ self.emit('EXEC_STMT') def visitCallFunc(self, node): + if self.emit_builtin_call(node): + return pos = 0 kw = 0 self.set_lineno(node) @@ -1024,6 +1028,35 @@ opcode = callfunc_opcode_info[ have_star*2 + have_dstar] self.emitop_int(opcode, kw << 8 | pos) + def emit_builtin_call(self, node): + if not self.space.config.objspace.opcodes.CALL_LIKELY_BUILTIN: + return False + if node.star_args is not None or node.dstar_args is not None: + return False + pos = 0 + # check for kw args + for arg in node.args: + if isinstance(arg, ast.Keyword): + return False + else: + pos = pos + 1 + func = node.node + if not isinstance(func, ast.Name): + return False + + name = func.varname + scope = self.scope.check_name(name) + # YYY + index = BUILTIN_TO_INDEX.get(name, -1) + if ((scope == SC_GLOBAL or + (scope == SC_DEFAULT and self.optimized and self.localsfullyknown)) + and index != -1): + for arg in node.args: + arg.accept(self) + self.emitop_int("CALL_LIKELY_BUILTIN", index << 8 | pos) + return True + return False + def visitPrint(self, node): self.set_lineno(node) if node.dest: Modified: pypy/branch/builtin-call-speedup-2/pypy/interpreter/module.py ============================================================================== --- pypy/branch/builtin-call-speedup-2/pypy/interpreter/module.py (original) +++ pypy/branch/builtin-call-speedup-2/pypy/interpreter/module.py Tue Dec 19 15:37:02 2006 @@ -10,7 +10,7 @@ def __init__(self, space, w_name, w_dict=None): self.space = space if w_dict is None: - w_dict = space.newdict() + w_dict = space.newdict(track_builtin_shadowing=True) self.w_dict = w_dict self.w_name = w_name if w_name is not None: Modified: pypy/branch/builtin-call-speedup-2/pypy/interpreter/pyopcode.py ============================================================================== --- pypy/branch/builtin-call-speedup-2/pypy/interpreter/pyopcode.py (original) +++ pypy/branch/builtin-call-speedup-2/pypy/interpreter/pyopcode.py Tue Dec 19 15:37:02 2006 @@ -874,6 +874,36 @@ def SET_LINENO(f, lineno, *ignored): pass + def CALL_LIKELY_BUILTIN(f, oparg, *ignored): + from pypy.module.__builtin__ import OPTIMIZED_BUILTINS, Module + from pypy.objspace.std.dictmultiobject import W_DictMultiObject + w_globals = f.w_globals + num = oparg >> 8 + assert isinstance(w_globals, W_DictMultiObject) + w_value = w_globals.implementation.get_builtin_indexed(num) + if w_value is None: + w_builtins = f.builtin + assert isinstance(w_builtins, Module) + w_builtin_dict = w_builtins.w_dict + assert isinstance(w_builtin_dict, W_DictMultiObject) + w_value = w_builtin_dict.implementation.get_builtin_indexed(num) +## if w_value is not None: +## print "CALL_LIKELY_BUILTIN fast" + if w_value is None: + varname = OPTIMIZED_BUILTINS[num] + message = "global name '%s' is not defined" % varname + raise OperationError(f.space.w_NameError, + f.space.wrap(message)) + nargs = oparg & 0xff + w_function = w_value + try: + w_result = f.space.call_valuestack(w_function, nargs, f.valuestack) + # XXX XXX fix the problem of resume points! + #rstack.resume_point("CALL_FUNCTION", f, nargs, returns=w_result) + finally: + f.valuestack.drop(nargs) + f.valuestack.push(w_result) + ## def EXTENDED_ARG(f, oparg, *ignored): ## opcode = f.nextop() ## oparg = oparg<<16 | f.nextarg() Modified: pypy/branch/builtin-call-speedup-2/pypy/module/__builtin__/__init__.py ============================================================================== --- pypy/branch/builtin-call-speedup-2/pypy/module/__builtin__/__init__.py (original) +++ pypy/branch/builtin-call-speedup-2/pypy/module/__builtin__/__init__.py Tue Dec 19 15:37:02 2006 @@ -1,6 +1,22 @@ from pypy.interpreter.error import OperationError from pypy.interpreter import module -from pypy.interpreter.mixedmodule import MixedModule +from pypy.interpreter.mixedmodule import MixedModule + +# put builtins here that should be optimized somehow + +OPTIMIZED_BUILTINS = ["len", "range", "xrange", "min", "max", "enumerate", + "isinstance", "type", "zip", "file", "open", "abs", "chr", "unichr", + "ord", "pow", "repr", "hash", "oct", "hex", "round", "cmp", "getattr", + "setattr", "delattr", "callable", "int", "str", "float"] + +assert len(OPTIMIZED_BUILTINS) <= 256 + +BUILTIN_TO_INDEX = {} + +for i, name in enumerate(OPTIMIZED_BUILTINS): + BUILTIN_TO_INDEX[name] = i + +assert len(OPTIMIZED_BUILTINS) == len(BUILTIN_TO_INDEX) class Module(MixedModule): """Built-in functions, exceptions, and other objects.""" @@ -141,6 +157,9 @@ def setup_after_space_initialization(self): """NOT_RPYTHON""" space = self.space + self.builtins_by_index = [None] * len(OPTIMIZED_BUILTINS) + for i, name in enumerate(OPTIMIZED_BUILTINS): + self.builtins_by_index[i] = space.getattr(self, space.wrap(name)) # call installations for pickle support for name in self.loaders.keys(): if name.startswith('_install_pickle_support_for_'): Modified: pypy/branch/builtin-call-speedup-2/pypy/module/__builtin__/test/test_builtin.py ============================================================================== --- pypy/branch/builtin-call-speedup-2/pypy/module/__builtin__/test/test_builtin.py (original) +++ pypy/branch/builtin-call-speedup-2/pypy/module/__builtin__/test/test_builtin.py Tue Dec 19 15:37:02 2006 @@ -449,6 +449,42 @@ raises(TypeError, hasattr, x, None) raises(TypeError, hasattr, x, 42) +class AppTestBuiltinOptimized(object): + def setup_class(cls): + from pypy.conftest import gettestobjspace + cls.space = gettestobjspace(**{"objspace.opcodes.CALL_LIKELY_BUILTIN": True}) + assert cls.space.config.objspace.opcodes.CALL_LIKELY_BUILTIN + + # hum, we need to invoke the compiler explicitely + def test_xrange_len(self): + s = """def test(): + x = xrange(33) + assert len(x) == 33 + x = xrange(33.2) + assert len(x) == 33 + x = xrange(33,0,-1) + assert len(x) == 33 + x = xrange(33,0) + assert len(x) == 0 + x = xrange(33,0.2) + assert len(x) == 0 + x = xrange(0,33) + assert len(x) == 33 + x = xrange(0,33,-1) + assert len(x) == 0 + x = xrange(0,33,2) + assert len(x) == 17 + x = xrange(0,32,2) + assert len(x) == 16 + """ + ns = {} + exec s in ns + ns["test"]() + + def test_delete_from_builtins(self): + s = """ """ + # XXX write this test! + class TestInternal: def setup_method(self,method): Modified: pypy/branch/builtin-call-speedup-2/pypy/objspace/std/dictmultiobject.py ============================================================================== --- pypy/branch/builtin-call-speedup-2/pypy/objspace/std/dictmultiobject.py (original) +++ pypy/branch/builtin-call-speedup-2/pypy/objspace/std/dictmultiobject.py Tue Dec 19 15:37:02 2006 @@ -1,6 +1,7 @@ import py from pypy.objspace.std.objspace import * from pypy.interpreter import gateway +from pypy.module.__builtin__.__init__ import BUILTIN_TO_INDEX, OPTIMIZED_BUILTINS from pypy.rlib.objectmodel import r_dict, we_are_translated @@ -54,6 +55,7 @@ ## def itervalues(self): ## pass + def keys(self): return [w_k for w_k in self.iterkeys()] def values(self): @@ -61,6 +63,14 @@ def items(self): return [(w_key, w_value) or w_key, w_value in self.iteritems()] +# the following method only makes sense when the option to use the +# CALL_LIKELY_BUILTIN opcode is set. Otherwise it won't even be seen +# by the annotator + def get_builtin_indexed(self, i): + w_key = self.space.wrap(OPTIMIZED_BUILTINS[i]) + return self.get(w_key) + + class EmptyDictImplementation(DictImplementation): def __init__(self, space): self.space = space @@ -312,8 +322,7 @@ def setitem(self, w_key, w_value): space = self.space if space.is_w(space.type(w_key), space.w_str): - self.content[space.str_w(w_key)] = w_value - return self + return self.setitem_str(w_key, w_value) else: return self._as_rdict().setitem(w_key, w_value) @@ -375,6 +384,37 @@ newimpl.setitem(self.space.wrap(k), w_v) return newimpl +class WaryDictImplementation(StrDictImplementation): + def __init__(self, space): + StrDictImplementation.__init__(self, space) + self.shadowed = [None] * len(BUILTIN_TO_INDEX) + + def setitem_str(self, w_key, w_value): + key = self.space.str_w(w_key) + i = BUILTIN_TO_INDEX.get(key, -1) + if i != -1: + self.shadowed[i] = w_value + self.content[key] = w_value + return self + + def delitem(self, w_key): + space = self.space + w_key_type = space.type(w_key) + if space.is_w(w_key_type, space.w_str): + key = space.str_w(w_key) + del self.content[key] + i = BUILTIN_TO_INDEX.get(key, -1) + if i != -1: + self.shadowed[i] = None + return self + elif self._is_sane_hash(w_key_type): + raise KeyError + else: + return self._as_rdict().delitem(w_key) + + def get_builtin_indexed(self, i): + return self.shadowed[i] + class RDictImplementation(DictImplementation): def __init__(self, space): self.space = space @@ -721,8 +761,10 @@ class W_DictMultiObject(W_Object): from pypy.objspace.std.dicttype import dict_typedef as typedef - def __init__(w_self, space, sharing=False): - if space.config.objspace.std.withdictmeasurement: + def __init__(w_self, space, wary=False, sharing=False): + if space.config.objspace.opcodes.CALL_LIKELY_BUILTIN and wary: + w_self.implementation = WaryDictImplementation(space) + elif space.config.objspace.std.withdictmeasurement: w_self.implementation = MeasuringDictImplementation(space) elif space.config.objspace.std.withsharingdict and sharing: w_self.implementation = SharedDictImplementation(space) Modified: pypy/branch/builtin-call-speedup-2/pypy/objspace/std/objspace.py ============================================================================== --- pypy/branch/builtin-call-speedup-2/pypy/objspace/std/objspace.py (original) +++ pypy/branch/builtin-call-speedup-2/pypy/objspace/std/objspace.py Tue Dec 19 15:37:02 2006 @@ -363,7 +363,10 @@ def newlist(self, list_w): return W_ListObject(list_w) - def newdict(self): + def newdict(self, track_builtin_shadowing=False): + if self.config.objspace.opcodes.CALL_LIKELY_BUILTIN and track_builtin_shadowing: + from pypy.objspace.std.dictmultiobject import W_DictMultiObject + return W_DictMultiObject(self, wary=True) return self.DictObjectCls(self) def newslice(self, w_start, w_end, w_step): From ericvrp at codespeak.net Tue Dec 19 17:18:00 2006 From: ericvrp at codespeak.net (ericvrp at codespeak.net) Date: Tue, 19 Dec 2006 17:18:00 +0100 (CET) Subject: [pypy-svn] r35895 - in pypy/dist/pypy/jit/codegen/llvm: . test Message-ID: <20061219161800.BCD1110075@code0.codespeak.net> Author: ericvrp Date: Tue Dec 19 17:17:59 2006 New Revision: 35895 Modified: pypy/dist/pypy/jit/codegen/llvm/rgenop.py pypy/dist/pypy/jit/codegen/llvm/test/test_genc_ts.py Log: jit/codegen/llvm supports the PYPYJITLOG environment variable like the i386 backend. Added getfield/setfield, fixes to getarrayitem/setarrayitem Modified: pypy/dist/pypy/jit/codegen/llvm/rgenop.py ============================================================================== --- pypy/dist/pypy/jit/codegen/llvm/rgenop.py (original) +++ pypy/dist/pypy/jit/codegen/llvm/rgenop.py Tue Dec 19 17:17:59 2006 @@ -1,4 +1,4 @@ -import py +import py, os from pypy.rlib.objectmodel import specialize from pypy.rpython.lltypesystem import lltype, llmemory from pypy.jit.codegen.model import AbstractRGenOp, GenLabel, GenBuilder @@ -14,10 +14,57 @@ PRINT_SOURCE = option.print_source PRINT_DEBUG = option.print_debug +WORD = 4 + + +class Logger: + + enabled = True + log_fd = -1 + + def _freeze_(self): + # reset the machine_code_dumper global instance to its default state + if self.log_fd >= 0: + os.close(self.log_fd) + self.__dict__.clear() + return False + + def open(self): + if not self.enabled: + return False + if self.log_fd < 0: + # check the environment for a file name + from pypy.rlib.ros import getenv + s = getenv('PYPYJITLOG') + if not s: + self.enabled = False + return False + try: + flags = os.O_WRONLY|os.O_CREAT|os.O_TRUNC + self.log_fd = os.open(s, flags, 0666) + except OSError: + os.write(2, "could not create log file\n") + self.enabled = False + return False + # log the executable name + from pypy.jit.codegen.hlinfo import highleveljitinfo + if highleveljitinfo.sys_executable: + os.write(self.log_fd, 'SYS_EXECUTABLE %s\n' % ( + highleveljitinfo.sys_executable,)) + return True + + def dump(self, s): + if not self.open(): + return + os.write(self.log_fd, str(s) + '\n') + +logger = Logger() + def log(s): if PRINT_DEBUG and not we_are_translated(): print str(s) + logger.dump(s) class Count(object): @@ -503,14 +550,59 @@ def op_float_is_true(self, gv_x): return self._is_true(gv_x, '0.0') + def genop_getfield(self, (offset, fieldsize), gv_ptr): + log('%s Builder.genop_getfield ([%d]%d) %s' % ( + self.block.label, offset, fieldsize, gv_ptr.operand())) + if fieldsize == WORD: + t = 'int' + else: + if fieldsize == 1: + t = 'ubyte' + else: + assert fieldsize == 2 + t = 'short' + gv_p = Var(t + '*') + self.asm.append(' %s=getelementptr %s,int %s' % ( + gv_p.operand2(), gv_ptr.operand(), offset / fieldsize)) + gv_result = Var(t) + self.asm.append(' %s=load %s' % ( + gv_result.operand2(), gv_p.operand())) + return gv_result + + def genop_setfield(self, (offset, fieldsize), gv_ptr, gv_value): + log('%s Builder.senop_setfield %s,([%d]%d) %s=%s' % ( + self.block.label, offset, fieldsize, gv_ptr.operand(), gv_value.operand())) + #if fieldsize == WORD: + # gv_result = Var('int') + #else: + # if fieldsize == 1: + # gv_result = Var('ubyte') + # else: + # assert fieldsize == 2 + # gv_result = Var('short') + gv_p = Var(gv_value.type+'*') + self.asm.append(' %s=getelementptr %s,int %s' % ( + gv_p.operand2(), gv_ptr.operand(), offset / fieldsize)) + self.asm.append(' store %s,%s' % ( + gv_value.operand2(), gv_p.operand())) + def genop_getarrayitem(self, arraytoken, gv_ptr, gv_index): - #XXX what about non char arrays? + array_length_offset, array_items_offset, itemsize = arraytoken log('%s Builder.genop_getarrayitem %s,%s,%s' % ( - self.block.label, arraytoken, gv_ptr, gv_index)) - gv_result = Var('ubyte') - gv_p = Var(gv_result.type+'*') #XXX get this from arraytoken - self.asm.append(' %s=getelementptr [0x%s]* %s,int 0,%s' % ( - gv_p.operand2(), gv_result.type, gv_ptr.operand2(), gv_index.operand())) + self.block.label, arraytoken, gv_ptr.operand(), gv_index.operand())) + + gv_i = Var(gv_index.type) + try: + offset = array_items_offset / itemsize + except TypeError: + offset = 4 #XXX (get inspired by ppc backend) + self.asm.append(' %s=add %s,%d' % ( + gv_i.operand2(), gv_index.operand(), offset)) #/itemsize correct? + + gv_p = Var(gv_ptr.type) + self.asm.append(' %s=getelementptr %s,%s' % ( + gv_p.operand2(), gv_ptr.operand(), gv_i.operand())) + gv_result = Var(gv_ptr.type[:-1]) self.asm.append(' %s=load %s' % ( gv_result.operand2(), gv_p.operand())) return gv_result @@ -523,6 +615,7 @@ return self.returnvar(eax) ''' #XXX TODO + array_length_offset, array_items_offset, itemsize = arraytoken gv_result = Var('int') log('%s Builder.genop_getarraysubstruct %s,%s,%s' % ( self.block.label, arraytoken, gv_ptr, gv_index)) @@ -537,6 +630,7 @@ return self.returnvar(mem(edx, lengthoffset)) ''' #XXX TODO + array_length_offset, array_items_offset, itemsize = arraytoken gv_result = Var('int') log('%s Builder.genop_getarraysize %s,%s' % ( self.block.label, arraytoken, gv_ptr)) @@ -545,26 +639,29 @@ return gv_result def genop_setarrayitem(self, arraytoken, gv_ptr, gv_index, gv_value): - #XXX what about non char arrays? + array_length_offset, array_items_offset, itemsize = arraytoken log('%s Builder.genop_setarrayitem %s,%s,%s,%s' % ( - self.block.label, arraytoken, gv_ptr, gv_index, gv_value)) - gv_p = Var('ubyte*') #XXX get this from arraytoken - self.asm.append(' %s=getelementptr [0x%s]* %s,int 0,%s' % ( - gv_p.operand2(), gv_ptr.type[:-1], gv_ptr.operand2(), gv_index.operand())) + self.block.label, arraytoken, gv_ptr.operand(), gv_index.operand(), gv_value.operand())) + + try: + offset = array_items_offset / itemsize + except TypeError: + offset = 4 #XXX (get inspired by ppc backend) + gv_i = Var(gv_index.type) + self.asm.append(' %s=add %s,%d' % ( + gv_i.operand2(), gv_index.operand(), offset)) #/itemsize correct? + + gv_p = Var(gv_ptr.type) + self.asm.append(' %s=getelementptr %s,%s' % ( + gv_p.operand2(), gv_ptr.operand(), gv_i.operand())) self.asm.append(' store %s,%s' % ( gv_value.operand(), gv_p.operand())) def genop_malloc_fixedsize(self, size): - ''' - # XXX boehm only, no atomic/non atomic distinction for now - self.push(imm(size)) - self.mc.CALL(rel32(gc_malloc_fnaddr())) - return self.returnvar(eax) - ''' log('%s Builder.genop_malloc_fixedsize %s' % ( - self.block.label, size)) + self.block.label, str(size))) gv_result = Var('ubyte*') - gv_gc_malloc_fnaddr = Var('[0xubyte]* (int)*') + gv_gc_malloc_fnaddr = Var('ubyte* (int)*') #XXX or use addGlobalFunctionMapping in libllvmjit.restart() self.asm.append(' %s=inttoptr int %d to %s ;gc_malloc_fnaddr' % ( gv_gc_malloc_fnaddr.operand2(), gc_malloc_fnaddr(), gv_gc_malloc_fnaddr.type)) @@ -573,22 +670,10 @@ return gv_result def genop_malloc_varsize(self, varsizealloctoken, gv_size): - ''' - # XXX boehm only, no atomic/non atomic distinction for now - # XXX no overflow checking for now - op_size = self.itemaddr(None, varsizealloctoken, gv_size) - self.mc.LEA(edx, op_size) - self.push(edx) - self.mc.CALL(rel32(gc_malloc_fnaddr())) - lengthoffset, _, _ = varsizealloctoken - self.mc.MOV(ecx, gv_size.operand(self)) - self.mc.MOV(mem(eax, lengthoffset), ecx) - return self.returnvar(eax) - ''' log('%s Builder.genop_malloc_varsize %s,%s' % ( - self.block.label, varsizealloctoken, gv_size)) + self.block.label, varsizealloctoken, gv_size.operand())) gv_result = Var('ubyte*') - gv_gc_malloc_fnaddr = Var('[0xubyte]* (int)*') + gv_gc_malloc_fnaddr = Var('ubyte* (int)*') #XXX or use addGlobalFunctionMapping in libllvmjit.restart() self.asm.append(' %s=inttoptr int %d to %s ;gc_malloc_fnaddr' % ( gv_gc_malloc_fnaddr.operand2(), gc_malloc_fnaddr(), gv_gc_malloc_fnaddr.type)) @@ -660,6 +745,7 @@ self.blocklist = None if PRINT_SOURCE: print asm_string + logger.dump(asm_string) llvmjit.parse(asm_string) llvmjit.transform(3) #optimize module (should be on functions actually) function = llvmjit.getNamedFunction(self.name) @@ -743,7 +829,12 @@ @staticmethod @specialize.memo() def fieldToken(T, name): - return (RLLVMGenOp.kindToken(T), llmemory.offsetof(T, name)) + FIELD = getattr(T, name) + if isinstance(FIELD, lltype.ContainerType): + fieldsize = 0 # not useful for getsubstruct + else: + fieldsize = llmemory.sizeof(FIELD) + return (llmemory.offsetof(T, name), fieldsize) @staticmethod @specialize.memo() @@ -797,3 +888,4 @@ global_rgenop = RLLVMGenOp() RLLVMGenOp.constPrebuiltGlobal = global_rgenop.genconst + 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 Tue Dec 19 17:17:59 2006 @@ -44,10 +44,10 @@ #test_normalize_indirect_call_more = skip #test_green_red_mismatch_in_call = skip #test_red_call_ignored_result = skip + #test_simple_struct = skip + #test_simple_array = skip #failing... - test_simple_struct = skip - test_simple_array = skip test_degenerated_before_return = skip test_degenerated_before_return_2 = skip test_degenerated_at_return = skip From stephan at codespeak.net Tue Dec 19 17:43:20 2006 From: stephan at codespeak.net (stephan at codespeak.net) Date: Tue, 19 Dec 2006 17:43:20 +0100 (CET) Subject: [pypy-svn] r35896 - pypy/dist/pypy/lib/app_test Message-ID: <20061219164320.8B9F51006E@code0.codespeak.net> Author: stephan Date: Tue Dec 19 17:43:19 2006 New Revision: 35896 Modified: pypy/dist/pypy/lib/app_test/test_stackless.py Log: added a couple of tests to test_stackless that are passing when running on CStackless, but skipping when running on pypy (not yet implemented features) Modified: pypy/dist/pypy/lib/app_test/test_stackless.py ============================================================================== --- pypy/dist/pypy/lib/app_test/test_stackless.py (original) +++ pypy/dist/pypy/lib/app_test/test_stackless.py Tue Dec 19 17:43:19 2006 @@ -7,10 +7,13 @@ from py.test import skip try: import stackless + stackless_c = True if 'coroutine' in dir(stackless): + stackless_c = False raise ImportError("We are running pypy-c") withinit = False except ImportError: + stackless_c = False try: from pypy.lib import stackless_new as stackless except ImportError, e: @@ -18,6 +21,11 @@ #from pypy.lib import stackless withinit = True +def pypy_skip(txt): + "don't skip, if we are running with CStackless" + if not stackless_c: + skip(txt) + class Test_Stackless: def setup_method(self, method): @@ -328,3 +336,128 @@ ('schedule', 1), ('schedule', 2), ('schedule', 1), ('schedule', 2),] + def test_channel_callback(self): + pypy_skip('not yet implemented in pypy') + res = [] + cb = [] + def callback_function(chan, task, sending, willblock): + cb.append((chan, task, sending, willblock)) + stackless.set_channel_callback(callback_function) + def f(chan): + chan.send('hello') + val = chan.receive() + res.append(val) + + chan = stackless.channel() + task = stackless.tasklet(f)(chan) + val = chan.receive() + res.append(val) + chan.send('world') + assert res == ['hello','world'] + maintask = stackless.getmain() + assert cb == [ + (chan, maintask, 0, 1), + (chan, task, 1, 0), + (chan, maintask, 1, 1), + (chan, task, 0, 0) + ] + + def test_schedule_callback(self): + pypy_skip('not yet implemented in pypy') + res = [] + cb = [] + def schedule_cb(prev, next): + cb.append((prev, next)) + + stackless.set_schedule_callback(schedule_cb) + def f(i): + res.append('A_%s' % i) + stackless.schedule() + res.append('B_%s' % i) + + t1 = stackless.tasklet(f)(1) + t2 = stackless.tasklet(f)(2) + maintask = stackless.getmain() + stackless.run() + assert res == ['A_1', 'A_2', 'B_1', 'B_2'] + assert cb == [ + (maintask, t1), + (t1, t2), + (t2, t1), + (t1, t2), + (t2, maintask) + ] + + def test_bomb(self): + pypy_skip('not yet implemented in pypy') + try: + 1/0 + except: + import sys + b = stackless.bomb(*sys.exc_info()) + assert b.type is ZeroDivisionError + print type(b.value) + assert str(b.value) == 'integer division or modulo by zero' + assert b.traceback is not None + + def test_send_exception(self): + pypy_skip('not yet implemented in pypy') + def exp_sender(chan): + chan.send_exception(Exception, 'test') + + def exp_recv(chan): + try: + val = chan.receive() + except Exception, exp: + assert exp.__class__ is Exception + assert str(exp) == 'test' + + chan = stackless.channel() + t1 = stackless.tasklet(exp_recv)(chan) + t2 = stackless.tasklet(exp_sender)(chan) + stackless.run() + + def test_send_sequence(self): + pypy_skip('not yet implemented in pypy') + res = [] + lst = [1,2,3,4,5,6,None] + iterable = iter(lst) + chan = stackless.channel() + def f(chan): + r = chan.receive() + while r: + res.append(r) + r = chan.receive() + + t = stackless.tasklet(f)(chan) + chan.send_sequence(iterable) + assert res == [1,2,3,4,5,6] + + def test_getruncount(self): + pypy_skip('not yet implemented in pypy') + assert stackless.getruncount() == 1 + def with_schedule(): + assert stackless.getruncount() == 2 + + t1 = stackless.tasklet(with_schedule)() + assert stackless.getruncount() == 2 + stackless.schedule() + def with_run(): + assert stackless.getruncount() == 1 + + t2 = stackless.tasklet(with_run)() + stackless.run() + + def test_schedule_return(self): + pypy_skip('not yet implemented in pypy') + def f():pass + t1= stackless.tasklet(f)() + r = stackless.schedule() + assert r is stackless.getmain() + t2 = stackless.tasklet(f)() + r = stackless.schedule('test') + assert r == 'test' + + + + From antocuni at codespeak.net Tue Dec 19 17:49:06 2006 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Tue, 19 Dec 2006 17:49:06 +0100 (CET) Subject: [pypy-svn] r35897 - in pypy/dist/pypy/translator/backendopt: . test Message-ID: <20061219164906.81E341006E@code0.codespeak.net> Author: antocuni Date: Tue Dec 19 17:49:05 2006 New Revision: 35897 Modified: pypy/dist/pypy/translator/backendopt/inline.py pypy/dist/pypy/translator/backendopt/test/test_inline.py Log: Other steps for making inline.py compatible with ootype. Modified: pypy/dist/pypy/translator/backendopt/inline.py ============================================================================== --- pypy/dist/pypy/translator/backendopt/inline.py (original) +++ pypy/dist/pypy/translator/backendopt/inline.py Tue Dec 19 17:49:05 2006 @@ -9,6 +9,7 @@ from pypy.annotation import model as annmodel from pypy.rpython.lltypesystem.lltype import Bool, Signed, typeOf, Void, Ptr from pypy.rpython.lltypesystem.lltype import normalizeptr +from pypy.rpython.ootypesystem import ootype from pypy.rpython import rmodel from pypy.tool.algo import sparsemat from pypy.translator.backendopt.support import log, split_block_with_keepalive @@ -92,15 +93,22 @@ i = len(ops)-1 while True: if isinstance(currvar, Constant): - return typeOf(normalizeptr(currvar.value)), block.exits[0] + value = currvar.value + if isinstance(typeOf(value), ootype.Instance): + TYPE = ootype.dynamicType(value) + else: + TYPE = typeOf(normalizeptr(value)) + return TYPE, block.exits[0] if i < 0: return None, None op = ops[i] i -= 1 - if op.opname in ("same_as", "cast_pointer") and op.result is currvar: + if op.opname in ("same_as", "cast_pointer", "ooupcast", "oodowncast") and op.result is currvar: currvar = op.args[0] elif op.opname == "malloc" and op.result is currvar: return Ptr(op.args[0].value), block.exits[0] + elif op.opname == "new" and op.result is currvar: + return op.args[0].value, block.exits[0] def does_raise_directly(graph, raise_analyzer): """ this function checks, whether graph contains operations which can raise @@ -285,7 +293,7 @@ self.rewire_exceptblock_with_guard(afterblock, copiedexceptblock) # generate blocks that do generic matching for cases when the # heuristic did not work - self.generic_exception_matching(afterblock, copiedexceptblock) # HERE + self.generic_exception_matching(afterblock, copiedexceptblock) def rewire_exceptblock_no_guard(self, afterblock, copiedexceptblock): # find all copied links that go to copiedexceptblock @@ -306,7 +314,7 @@ def rewire_exceptblock_with_guard(self, afterblock, copiedexceptblock): # this rewiring does not always succeed. in the cases where it doesn't # there will be generic code inserted - from pypy.rpython.lltypesystem import rclass + rclass = self.translator.rtyper.type_system.rclass exc_match = self.translator.rtyper.getexceptiondata().fn_exception_match for link in self.entrymap[self.graph_to_inline.exceptblock]: copiedblock = self.copy_block(link.prevblock) @@ -370,7 +378,7 @@ blocks[-1].exits[0].exitcase = None del blocks[-1].exits[0].llexitcase linkargs = copiedexceptblock.inputargs - copiedexceptblock.recloseblock(Link(linkargs, blocks[0])) ## HERE + copiedexceptblock.recloseblock(Link(linkargs, blocks[0])) copiedexceptblock.operations += generate_keepalive(linkargs) @@ -470,6 +478,8 @@ total += 1.5 + len(op.args) / 2 elif op.opname == "indirect_call": total += 2 + len(op.args) / 2 + elif op.opname == "oosend": + total += 2 + len(op.args) / 2 total += weights.get(op.opname, 1) if block.exitswitch is not None: total += 1 Modified: pypy/dist/pypy/translator/backendopt/test/test_inline.py ============================================================================== --- pypy/dist/pypy/translator/backendopt/test/test_inline.py (original) +++ pypy/dist/pypy/translator/backendopt/test/test_inline.py Tue Dec 19 17:49:05 2006 @@ -359,7 +359,6 @@ py.test.raises(CannotInline, self.check_inline, factorial, f, [int]) def test_auto_inlining_small_call_big(self): - self._skip_oo('exception rewiring') def leaf(n): total = 0 i = 0 @@ -386,7 +385,6 @@ assert result == -1 def test_auto_inlining_small_call_big_call_count(self): - self._skip_oo('exception rewiring') def leaf(n): total = 0 i = 0 From santagada at codespeak.net Tue Dec 19 19:09:50 2006 From: santagada at codespeak.net (santagada at codespeak.net) Date: Tue, 19 Dec 2006 19:09:50 +0100 (CET) Subject: [pypy-svn] r35898 - in pypy/dist/pypy/lang/js: . test Message-ID: <20061219180950.A933610078@code0.codespeak.net> Author: santagada Date: Tue Dec 19 19:09:40 2006 New Revision: 35898 Modified: pypy/dist/pypy/lang/js/context.py pypy/dist/pypy/lang/js/interpreter.py pypy/dist/pypy/lang/js/test/test_interp.py pypy/dist/pypy/lang/js/test/test_parser.py Log: Finishing the work on cleaning up the code and making some tests work again 4 test passing, 31 failling... still better than nothing Modified: pypy/dist/pypy/lang/js/context.py ============================================================================== --- pypy/dist/pypy/lang/js/context.py (original) +++ pypy/dist/pypy/lang/js/context.py Tue Dec 19 19:09:40 2006 @@ -1,6 +1,5 @@ # encoding: utf-8 -from copy import copy from pypy.lang.js.jsobj import w_Undefined, Property from pypy.lang.js.reference import Reference @@ -28,17 +27,17 @@ return Reference(property_name) -def global_context(global): +def global_context(w_global): ctx = ExecutionContext() - ctx.push_object(global) - ctx.this = global - ctx.variable = global + ctx.push_object(w_global) + ctx.this = w_global + ctx.variable = w_global ctx.property = Property('', w_Undefined, DontDelete=True) return ctx def eval_context(calling_context): ctx = ExecutionContext() - ctx.scope = copy(calling_context.scope) + ctx.scope = calling_context.scope[:] ctx.this = calling_context.this ctx.variable = calling_context.variable ctx.property = Property('', w_Undefined) Modified: pypy/dist/pypy/lang/js/interpreter.py ============================================================================== --- pypy/dist/pypy/lang/js/interpreter.py (original) +++ pypy/dist/pypy/lang/js/interpreter.py Tue Dec 19 19:09:40 2006 @@ -236,30 +236,30 @@ return W_Number(num_left + num_right) class __extend__(Script): - def call(self, context=None, args=(), params=[], this=w_Undefined, first = False): - ncontext = ExecutionContext(context) - for i, item in enumerate(params): - try: - temp = args[i] - except IndexError: - temp = w_Undefined - ncontext.assign(item, temp) - - for var in self.var_decl: - if first: - ncontext.globals[var.name] = w_Undefined - else: - ncontext.locals[var.name] = w_Undefined - - w_Arguments = W_Arguments(dict([(str(x),y) for x,y in enumerate(args)])) - ncontext.assign('arguments', w_Arguments) - - ncontext.assign('this', this) + def call(self, ctx): + # ncontext = ExecutionContext(context) + # for i, item in enumerate(params): + # try: + # temp = args[i] + # except IndexError: + # temp = w_Undefined + # ncontext.assign(item, temp) + # + # for var in self.var_decl: + # if first: + # ncontext.globals[var.name] = w_Undefined + # else: + # ncontext.locals[var.name] = w_Undefined + + # w_Arguments = W_Arguments(dict([(str(x),y) for x,y in enumerate(args)])) + # ncontext.assign('arguments', w_Arguments) + # + # ncontext.assign('this', this) try: last = w_Undefined for node in self.nodes: - last = node.call(ncontext) + last = node.call(ctx) return last except ExecutionReturned, e: return e.value Modified: pypy/dist/pypy/lang/js/test/test_interp.py ============================================================================== --- pypy/dist/pypy/lang/js/test/test_interp.py (original) +++ pypy/dist/pypy/lang/js/test/test_interp.py Tue Dec 19 19:09:40 2006 @@ -12,18 +12,12 @@ from StringIO import StringIO -def parse_d(code): - return build_interpreter(parse(code)) - def js_is_on_path(): try: py.path.local.sysfind("js") except py.error.ENOENT: - return False - return True + py.test.skip("js binary not found") -if not js_is_on_path(): - py.test.skip("js binary not found") class TestInterp(object): @@ -34,7 +28,7 @@ l = [] interpreter.writer = l.append Script([Semicolon(Call(Identifier('print', None), - List([Number(1), Number(2)])))],[],[]).call() + List([Number(1), Number(2)])))],[],[]).call(ExecutionContext()) assert l == ['1,2'] def assert_prints(self, code, assval): Modified: pypy/dist/pypy/lang/js/test/test_parser.py ============================================================================== --- pypy/dist/pypy/lang/js/test/test_parser.py (original) +++ pypy/dist/pypy/lang/js/test/test_parser.py Tue Dec 19 19:09:40 2006 @@ -3,8 +3,7 @@ import py -if not js_is_on_path(): - py.test.skip("js binary not found") +js_is_on_path() def test_read_js_output(): From mwh at codespeak.net Tue Dec 19 19:11:56 2006 From: mwh at codespeak.net (mwh at codespeak.net) Date: Tue, 19 Dec 2006 19:11:56 +0100 (CET) Subject: [pypy-svn] r35899 - pypy/branch/builtin-call-speedup-2/pypy/objspace/std Message-ID: <20061219181156.111F810078@code0.codespeak.net> Author: mwh Date: Tue Dec 19 19:11:55 2006 New Revision: 35899 Modified: pypy/branch/builtin-call-speedup-2/pypy/objspace/std/dictmultiobject.py Log: one small mismerge Modified: pypy/branch/builtin-call-speedup-2/pypy/objspace/std/dictmultiobject.py ============================================================================== --- pypy/branch/builtin-call-speedup-2/pypy/objspace/std/dictmultiobject.py (original) +++ pypy/branch/builtin-call-speedup-2/pypy/objspace/std/dictmultiobject.py Tue Dec 19 19:11:55 2006 @@ -407,7 +407,7 @@ if i != -1: self.shadowed[i] = None return self - elif self._is_sane_hash(w_key_type): + elif _is_sane_hash(space, w_key_type): raise KeyError else: return self._as_rdict().delitem(w_key) From mwh at codespeak.net Tue Dec 19 19:19:45 2006 From: mwh at codespeak.net (mwh at codespeak.net) Date: Tue, 19 Dec 2006 19:19:45 +0100 (CET) Subject: [pypy-svn] r35900 - in pypy/dist: lib-python/modified-2.4.1 pypy/config pypy/interpreter pypy/interpreter/astcompiler pypy/module/__builtin__ pypy/module/__builtin__/test pypy/objspace/std Message-ID: <20061219181945.E864B10075@code0.codespeak.net> Author: mwh Date: Tue Dec 19 19:19:44 2006 New Revision: 35900 Modified: pypy/dist/lib-python/modified-2.4.1/opcode.py pypy/dist/pypy/config/pypyoption.py pypy/dist/pypy/interpreter/astcompiler/pycodegen.py pypy/dist/pypy/interpreter/module.py pypy/dist/pypy/interpreter/pyopcode.py pypy/dist/pypy/module/__builtin__/__init__.py pypy/dist/pypy/module/__builtin__/test/test_builtin.py pypy/dist/pypy/objspace/std/dictmultiobject.py pypy/dist/pypy/objspace/std/objspace.py Log: merge builtin-call-speedup-2. gives ~10% on richards, a bit less on pystone. --objspace-opcodes-CALL_LIKELY_BUILTIN to enable. Modified: pypy/dist/lib-python/modified-2.4.1/opcode.py ============================================================================== --- pypy/dist/lib-python/modified-2.4.1/opcode.py (original) +++ pypy/dist/lib-python/modified-2.4.1/opcode.py Tue Dec 19 19:19:44 2006 @@ -187,4 +187,7 @@ def_op('EXTENDED_ARG', 143) EXTENDED_ARG = 143 +# pypy modification, experimental bytecode +def_op('CALL_LIKELY_BUILTIN', 144) # #args + (#kwargs << 8) + del def_op, name_op, jrel_op, jabs_op Modified: pypy/dist/pypy/config/pypyoption.py ============================================================================== --- pypy/dist/pypy/config/pypyoption.py (original) +++ pypy/dist/pypy/config/pypyoption.py Tue Dec 19 19:19:44 2006 @@ -38,6 +38,10 @@ cmdline='--compiler'), OptionDescription("opcodes", "opcodes to enable in the interpreter", [ + BoolOption("CALL_LIKELY_BUILTIN", "emit a special bytecode for likely calls to builtin functions", + default=False, + requires=[("objspace.usepycfiles", False), + ("objspace.std.withmultidict", True)]) ]), BoolOption("nofaking", "disallow faking in the object space", Modified: pypy/dist/pypy/interpreter/astcompiler/pycodegen.py ============================================================================== --- pypy/dist/pypy/interpreter/astcompiler/pycodegen.py (original) +++ pypy/dist/pypy/interpreter/astcompiler/pycodegen.py Tue Dec 19 19:19:44 2006 @@ -30,6 +30,8 @@ TRY_FINALLY = 3 END_FINALLY = 4 +from pypy.module.__builtin__.__init__ import BUILTIN_TO_INDEX + def compileFile(filename, display=0): f = open(filename, 'U') buf = f.read() @@ -1005,6 +1007,8 @@ self.emit('EXEC_STMT') def visitCallFunc(self, node): + if self.emit_builtin_call(node): + return pos = 0 kw = 0 self.set_lineno(node) @@ -1024,6 +1028,35 @@ opcode = callfunc_opcode_info[ have_star*2 + have_dstar] self.emitop_int(opcode, kw << 8 | pos) + def emit_builtin_call(self, node): + if not self.space.config.objspace.opcodes.CALL_LIKELY_BUILTIN: + return False + if node.star_args is not None or node.dstar_args is not None: + return False + pos = 0 + # check for kw args + for arg in node.args: + if isinstance(arg, ast.Keyword): + return False + else: + pos = pos + 1 + func = node.node + if not isinstance(func, ast.Name): + return False + + name = func.varname + scope = self.scope.check_name(name) + # YYY + index = BUILTIN_TO_INDEX.get(name, -1) + if ((scope == SC_GLOBAL or + (scope == SC_DEFAULT and self.optimized and self.localsfullyknown)) + and index != -1): + for arg in node.args: + arg.accept(self) + self.emitop_int("CALL_LIKELY_BUILTIN", index << 8 | pos) + return True + return False + def visitPrint(self, node): self.set_lineno(node) if node.dest: Modified: pypy/dist/pypy/interpreter/module.py ============================================================================== --- pypy/dist/pypy/interpreter/module.py (original) +++ pypy/dist/pypy/interpreter/module.py Tue Dec 19 19:19:44 2006 @@ -10,7 +10,7 @@ def __init__(self, space, w_name, w_dict=None): self.space = space if w_dict is None: - w_dict = space.newdict() + w_dict = space.newdict(track_builtin_shadowing=True) self.w_dict = w_dict self.w_name = w_name if w_name is not None: Modified: pypy/dist/pypy/interpreter/pyopcode.py ============================================================================== --- pypy/dist/pypy/interpreter/pyopcode.py (original) +++ pypy/dist/pypy/interpreter/pyopcode.py Tue Dec 19 19:19:44 2006 @@ -874,6 +874,36 @@ def SET_LINENO(f, lineno, *ignored): pass + def CALL_LIKELY_BUILTIN(f, oparg, *ignored): + from pypy.module.__builtin__ import OPTIMIZED_BUILTINS, Module + from pypy.objspace.std.dictmultiobject import W_DictMultiObject + w_globals = f.w_globals + num = oparg >> 8 + assert isinstance(w_globals, W_DictMultiObject) + w_value = w_globals.implementation.get_builtin_indexed(num) + if w_value is None: + w_builtins = f.builtin + assert isinstance(w_builtins, Module) + w_builtin_dict = w_builtins.w_dict + assert isinstance(w_builtin_dict, W_DictMultiObject) + w_value = w_builtin_dict.implementation.get_builtin_indexed(num) +## if w_value is not None: +## print "CALL_LIKELY_BUILTIN fast" + if w_value is None: + varname = OPTIMIZED_BUILTINS[num] + message = "global name '%s' is not defined" % varname + raise OperationError(f.space.w_NameError, + f.space.wrap(message)) + nargs = oparg & 0xff + w_function = w_value + try: + w_result = f.space.call_valuestack(w_function, nargs, f.valuestack) + # XXX XXX fix the problem of resume points! + #rstack.resume_point("CALL_FUNCTION", f, nargs, returns=w_result) + finally: + f.valuestack.drop(nargs) + f.valuestack.push(w_result) + ## def EXTENDED_ARG(f, oparg, *ignored): ## opcode = f.nextop() ## oparg = oparg<<16 | f.nextarg() Modified: pypy/dist/pypy/module/__builtin__/__init__.py ============================================================================== --- pypy/dist/pypy/module/__builtin__/__init__.py (original) +++ pypy/dist/pypy/module/__builtin__/__init__.py Tue Dec 19 19:19:44 2006 @@ -1,6 +1,22 @@ from pypy.interpreter.error import OperationError from pypy.interpreter import module -from pypy.interpreter.mixedmodule import MixedModule +from pypy.interpreter.mixedmodule import MixedModule + +# put builtins here that should be optimized somehow + +OPTIMIZED_BUILTINS = ["len", "range", "xrange", "min", "max", "enumerate", + "isinstance", "type", "zip", "file", "open", "abs", "chr", "unichr", + "ord", "pow", "repr", "hash", "oct", "hex", "round", "cmp", "getattr", + "setattr", "delattr", "callable", "int", "str", "float"] + +assert len(OPTIMIZED_BUILTINS) <= 256 + +BUILTIN_TO_INDEX = {} + +for i, name in enumerate(OPTIMIZED_BUILTINS): + BUILTIN_TO_INDEX[name] = i + +assert len(OPTIMIZED_BUILTINS) == len(BUILTIN_TO_INDEX) class Module(MixedModule): """Built-in functions, exceptions, and other objects.""" @@ -141,6 +157,9 @@ def setup_after_space_initialization(self): """NOT_RPYTHON""" space = self.space + self.builtins_by_index = [None] * len(OPTIMIZED_BUILTINS) + for i, name in enumerate(OPTIMIZED_BUILTINS): + self.builtins_by_index[i] = space.getattr(self, space.wrap(name)) # call installations for pickle support for name in self.loaders.keys(): if name.startswith('_install_pickle_support_for_'): Modified: pypy/dist/pypy/module/__builtin__/test/test_builtin.py ============================================================================== --- pypy/dist/pypy/module/__builtin__/test/test_builtin.py (original) +++ pypy/dist/pypy/module/__builtin__/test/test_builtin.py Tue Dec 19 19:19:44 2006 @@ -449,6 +449,42 @@ raises(TypeError, hasattr, x, None) raises(TypeError, hasattr, x, 42) +class AppTestBuiltinOptimized(object): + def setup_class(cls): + from pypy.conftest import gettestobjspace + cls.space = gettestobjspace(**{"objspace.opcodes.CALL_LIKELY_BUILTIN": True}) + assert cls.space.config.objspace.opcodes.CALL_LIKELY_BUILTIN + + # hum, we need to invoke the compiler explicitely + def test_xrange_len(self): + s = """def test(): + x = xrange(33) + assert len(x) == 33 + x = xrange(33.2) + assert len(x) == 33 + x = xrange(33,0,-1) + assert len(x) == 33 + x = xrange(33,0) + assert len(x) == 0 + x = xrange(33,0.2) + assert len(x) == 0 + x = xrange(0,33) + assert len(x) == 33 + x = xrange(0,33,-1) + assert len(x) == 0 + x = xrange(0,33,2) + assert len(x) == 17 + x = xrange(0,32,2) + assert len(x) == 16 + """ + ns = {} + exec s in ns + ns["test"]() + + def test_delete_from_builtins(self): + s = """ """ + # XXX write this test! + class TestInternal: def setup_method(self,method): Modified: pypy/dist/pypy/objspace/std/dictmultiobject.py ============================================================================== --- pypy/dist/pypy/objspace/std/dictmultiobject.py (original) +++ pypy/dist/pypy/objspace/std/dictmultiobject.py Tue Dec 19 19:19:44 2006 @@ -1,6 +1,7 @@ import py from pypy.objspace.std.objspace import * from pypy.interpreter import gateway +from pypy.module.__builtin__.__init__ import BUILTIN_TO_INDEX, OPTIMIZED_BUILTINS from pypy.rlib.objectmodel import r_dict, we_are_translated @@ -54,6 +55,7 @@ ## def itervalues(self): ## pass + def keys(self): return [w_k for w_k in self.iterkeys()] def values(self): @@ -61,6 +63,14 @@ def items(self): return [(w_key, w_value) or w_key, w_value in self.iteritems()] +# the following method only makes sense when the option to use the +# CALL_LIKELY_BUILTIN opcode is set. Otherwise it won't even be seen +# by the annotator + def get_builtin_indexed(self, i): + w_key = self.space.wrap(OPTIMIZED_BUILTINS[i]) + return self.get(w_key) + + class EmptyDictImplementation(DictImplementation): def __init__(self, space): self.space = space @@ -312,8 +322,7 @@ def setitem(self, w_key, w_value): space = self.space if space.is_w(space.type(w_key), space.w_str): - self.content[space.str_w(w_key)] = w_value - return self + return self.setitem_str(w_key, w_value) else: return self._as_rdict().setitem(w_key, w_value) @@ -375,6 +384,37 @@ newimpl.setitem(self.space.wrap(k), w_v) return newimpl +class WaryDictImplementation(StrDictImplementation): + def __init__(self, space): + StrDictImplementation.__init__(self, space) + self.shadowed = [None] * len(BUILTIN_TO_INDEX) + + def setitem_str(self, w_key, w_value): + key = self.space.str_w(w_key) + i = BUILTIN_TO_INDEX.get(key, -1) + if i != -1: + self.shadowed[i] = w_value + self.content[key] = w_value + return self + + def delitem(self, w_key): + space = self.space + w_key_type = space.type(w_key) + if space.is_w(w_key_type, space.w_str): + key = space.str_w(w_key) + del self.content[key] + i = BUILTIN_TO_INDEX.get(key, -1) + if i != -1: + self.shadowed[i] = None + return self + elif _is_sane_hash(space, w_key_type): + raise KeyError + else: + return self._as_rdict().delitem(w_key) + + def get_builtin_indexed(self, i): + return self.shadowed[i] + class RDictImplementation(DictImplementation): def __init__(self, space): self.space = space @@ -721,8 +761,10 @@ class W_DictMultiObject(W_Object): from pypy.objspace.std.dicttype import dict_typedef as typedef - def __init__(w_self, space, sharing=False): - if space.config.objspace.std.withdictmeasurement: + def __init__(w_self, space, wary=False, sharing=False): + if space.config.objspace.opcodes.CALL_LIKELY_BUILTIN and wary: + w_self.implementation = WaryDictImplementation(space) + elif space.config.objspace.std.withdictmeasurement: w_self.implementation = MeasuringDictImplementation(space) elif space.config.objspace.std.withsharingdict and sharing: w_self.implementation = SharedDictImplementation(space) Modified: pypy/dist/pypy/objspace/std/objspace.py ============================================================================== --- pypy/dist/pypy/objspace/std/objspace.py (original) +++ pypy/dist/pypy/objspace/std/objspace.py Tue Dec 19 19:19:44 2006 @@ -363,7 +363,10 @@ def newlist(self, list_w): return W_ListObject(list_w) - def newdict(self): + def newdict(self, track_builtin_shadowing=False): + if self.config.objspace.opcodes.CALL_LIKELY_BUILTIN and track_builtin_shadowing: + from pypy.objspace.std.dictmultiobject import W_DictMultiObject + return W_DictMultiObject(self, wary=True) return self.DictObjectCls(self) def newslice(self, w_start, w_end, w_step): From mwh at codespeak.net Tue Dec 19 19:23:39 2006 From: mwh at codespeak.net (mwh at codespeak.net) Date: Tue, 19 Dec 2006 19:23:39 +0100 (CET) Subject: [pypy-svn] r35901 - pypy/dist/pypy/translator/goal Message-ID: <20061219182339.7E19910078@code0.codespeak.net> Author: mwh Date: Tue Dec 19 19:23:38 2006 New Revision: 35901 Modified: pypy/dist/pypy/translator/goal/bench-cronjob.py Log: let's benchmark some call-likely-builtin builds tonight. Modified: pypy/dist/pypy/translator/goal/bench-cronjob.py ============================================================================== --- pypy/dist/pypy/translator/goal/bench-cronjob.py (original) +++ pypy/dist/pypy/translator/goal/bench-cronjob.py Tue Dec 19 19:23:38 2006 @@ -166,10 +166,12 @@ if backends == []: #_ prefix means target specific option, # prefix to outcomment backends = [backend.strip() for backend in """ llvm--_objspace-std-withstrdict + llvm--_objspace-opcodes-CALL_LIKELY_BUILTIN c c--gc=framework c--thread--_objspace-std-withstrdict--profopt='-c "from richards import *;main(iterations=1)"' c--stackless + c--stackless--profopt='-c "from richards import *;main(iterations=1)"'--_objspace-opcodes-CALL_LIKELY_BUILTIN c--stackless--_objspace-std-withstrdict--profopt='-c "from richards import *;main(iterations=1)"' c--profopt='-c "from richards import *;main(iterations=1)"' c--_objspace-std-withstrdict--profopt='-c "from richards import *;main(iterations=1)"' From mwh at codespeak.net Tue Dec 19 19:30:26 2006 From: mwh at codespeak.net (mwh at codespeak.net) Date: Tue, 19 Dec 2006 19:30:26 +0100 (CET) Subject: [pypy-svn] r35902 - in pypy/branch: builtin-call-speedup builtin-call-speedup-2 Message-ID: <20061219183026.3AE5810078@code0.codespeak.net> Author: mwh Date: Tue Dec 19 19:30:22 2006 New Revision: 35902 Removed: pypy/branch/builtin-call-speedup/ pypy/branch/builtin-call-speedup-2/ Log: delete merged branch. From santagada at codespeak.net Tue Dec 19 21:29:15 2006 From: santagada at codespeak.net (santagada at codespeak.net) Date: Tue, 19 Dec 2006 21:29:15 +0100 (CET) Subject: [pypy-svn] r35904 - in pypy/dist/pypy/lang/js: . test Message-ID: <20061219202915.6741610079@code0.codespeak.net> Author: santagada Date: Tue Dec 19 21:28:59 2006 New Revision: 35904 Modified: pypy/dist/pypy/lang/js/astgen.py pypy/dist/pypy/lang/js/context.py pypy/dist/pypy/lang/js/interpreter.py pypy/dist/pypy/lang/js/jsobj.py pypy/dist/pypy/lang/js/reference.py pypy/dist/pypy/lang/js/test/test_interp.py Log: 17 tests passing, and now following the specs!!! Modified: pypy/dist/pypy/lang/js/astgen.py ============================================================================== --- pypy/dist/pypy/lang/js/astgen.py (original) +++ pypy/dist/pypy/lang/js/astgen.py Tue Dec 19 21:28:59 2006 @@ -22,9 +22,9 @@ self.items = items class Assign(Node): - def __init__(self, identifier, expr): - self.identifier = identifier - self.expr = expr + def __init__(self, LHSExp, AssignmentExp): + self.LHSExp = LHSExp + self.AssignmentExp = AssignmentExp class Block(Node): def __init__(self, nodes): Modified: pypy/dist/pypy/lang/js/context.py ============================================================================== --- pypy/dist/pypy/lang/js/context.py (original) +++ pypy/dist/pypy/lang/js/context.py Tue Dec 19 21:28:59 2006 @@ -11,6 +11,14 @@ self.variable = None self.property = Property('',w_Undefined) #Attribute flags for new vars + def assign(self, name, value): + """ + assign to property name, creating it if it doesn't exist + """ + pass + #ref = self.resolve_identifier(name) + #if ref. + def push_object(self, obj): """push object into scope stack""" self.scope.insert(0, obj) @@ -22,9 +30,9 @@ def resolve_identifier(self, identifier): for obj in self.scope: if obj.HasProperty(identifier): - return Reference(property_name, obj) + return Reference(identifier, obj) - return Reference(property_name) + return Reference(identifier) def global_context(w_global): Modified: pypy/dist/pypy/lang/js/interpreter.py ============================================================================== --- pypy/dist/pypy/lang/js/interpreter.py (original) +++ pypy/dist/pypy/lang/js/interpreter.py Tue Dec 19 21:28:59 2006 @@ -1,7 +1,7 @@ from pypy.lang.js.astgen import * from pypy.lang.js.jsparser import parse -from pypy.lang.js.context import ExecutionContext +from pypy.lang.js.context import * from pypy.lang.js.jsobj import W_Number, W_String, W_Object from pypy.lang.js.jsobj import w_Undefined, W_Arguments, W_Boolean, NaN @@ -22,11 +22,11 @@ def __init__(self, script_source=None): self.w_Object = W_Object() #creating Object self.w_Global = W_Object() - w_Global.Prototype = w_Object - w_Global.Set('prototype', 'Object') - w_Global.Set('Object', w_Object) - self.global_context = GlobalContext(w_global) - if script_source is not none: + self.w_Global.Prototype = self.w_Object + self.w_Global.Put('prototype', 'Object') + self.w_Global.Put('Object', self.w_Object) + self.global_context = global_context(self.w_Global) + if script_source is not None: self.load_source(script_source) def load_source(self, script_source): @@ -36,7 +36,7 @@ def run(self): """run the interpreter""" - self.script.Call(self.global_context) + self.script.call(self.global_context) @@ -46,9 +46,11 @@ return W_Array(d) class __extend__(Assign): - def call(self, context): - val = self.expr.call(context) - self.identifier.put(context,val) + def call(self, ctx): + v1 = self.LHSExp.call(ctx) + v3 = self.AssignmentExp.call(ctx).GetValue() + v1.PutValue(v3, ctx) + return v3 class __extend__(Block): def call(self, context): @@ -64,7 +66,7 @@ def call(self, context): name = self.identifier.get_literal() if name == 'print': - writer(",".join([i.ToString() for i in self.arglist.call(context)])) + writer(",".join([i.GetValue().ToString() for i in self.arglist.call(context)])) else: backup_scope = scope_manager.current_scope @@ -108,14 +110,11 @@ return w_obj class __extend__(Identifier): - def call(self, context): - if self.initialiser is not None: - context.assign(self.name, self.initialiser.call(context)) - try: - value = context.access(self.name) - return value - except NameError: - return scope_manager.get_variable(self.name) + def call(self, ctx): + # if self.initialiser is not None: + # context.assign(self.name, self.initialiser.call(context)) + value = ctx.resolve_identifier(self.name) + return value def put(self, context, val, obj=None): context.assign(self.name, val) @@ -222,8 +221,8 @@ def call(self, context=None): left = self.left.call(context).GetValue() right = self.right.call(context).GetValue() - prim_left = left.ToPrimitive() - prim_right = right.ToPrimitive() + prim_left = left.ToPrimitive('Number') + prim_right = right.ToPrimitive('Number') # INSANE if isinstance(prim_left, W_String) or isinstance(prim_right, W_String): str_left = prim_left.ToString() @@ -305,16 +304,16 @@ return tryresult class __extend__(Undefined): - def call(self, context=None): + def call(self, ctx): return None class __extend__(Vars): - def call(self, context=None): + def call(self, ctx): for var in self.nodes: - var.call(context) + var.call(ctx) class __extend__(While): - def call(self, context=None): - while self.condition.call(context).ToBoolean(): - self.body.call(context) + def call(self, ctx): + while self.condition.call(ctx).ToBoolean(): + self.body.call(ctx) Modified: pypy/dist/pypy/lang/js/jsobj.py ============================================================================== --- pypy/dist/pypy/lang/js/jsobj.py (original) +++ pypy/dist/pypy/lang/js/jsobj.py Tue Dec 19 21:28:59 2006 @@ -24,26 +24,29 @@ return self def ToBoolean(self): - return bool(self) + return False def ToPrimitive(self, hint=""): return self - #def ToNumber(self): - # return int(self.ToPrimitive(hint="number")) - def ToString(self): return str(self) def ToObject(self): return self + def ToNumber(self): + return NaN + def __repr__(self): return "<%s(%s)>" % (self.__class__.__name__, str(self)) class W_Primitive(W_Root): """unifying parent for primitives""" - pass + def ToPrimitive(self, PreferredType): + return self + + class W_Object(W_Root): def __init__(self, function=None): @@ -116,6 +119,8 @@ else: #suppose hint is "Number" dunno what to do otherwise internal_def_value("valueOf", "toString") + ToPrimitive = DefaultValue + def __str__(self): return "[object %s]"%(self.Class,) @@ -147,31 +152,24 @@ def ToBoolean(self): return False -class W_Boolean(W_Root): +class W_Boolean(W_Primitive): def __init__(self, boolval): self.boolval = bool(boolval) - def __str__(self): + def ToString(self): if self.boolval: return "true" return "false" def ToNumber(self): if self.boolval: - return 1 - return 0 - - def ToBoolean(self): - return self.boolval - + return 1.0 + return 0.0 -class W_String(W_Root): +class W_String(W_Primitive): def __init__(self, strval): self.strval = strval -# def ToString(self): -# return self.strval - def __str__(self): return self.strval @@ -179,13 +177,11 @@ return bool(self.strval) -class W_Number(W_Root): +class W_Number(W_Primitive): def __init__(self, floatval): self.floatval = floatval - def __str__(self): - # XXX: more attention - # cough, cough + def ToString(self): if str(self.floatval) == str(NaN): return 'NaN' if float(int(self.floatval)) == self.floatval: @@ -193,21 +189,22 @@ return str(self.floatval) def ToBoolean(self): - return bool(self.floatval) + return W_Boolean(bool(self.floatval)) + def ToNumber(self): + return self.floatval + def Get(self, name): return w_Undefined - def ToNumber(self): - return self.floatval class W_Reference(W_Root): def GetValue(self): raise NotImplementedError("W_Reference.GetValue") -class W_Builtin(W_Object): +class W_Builtin(W_Root): def __init__(self, builtinfunction): - W_Object.__init__() + #W_Object.__init__(self) self.builtinfunction = builtinfunction def Call(self, context, args=[], this = None): @@ -226,11 +223,4 @@ w_Undefined = W_Undefined() w_Null = W_Null() -def to_primitive(Value, PreferredType): - assert isinstance(Value, W_Root) - if isinstance(Value, W_Object): - return Value.DefaultValue(PreferredType) - return Value - - \ No newline at end of file Modified: pypy/dist/pypy/lang/js/reference.py ============================================================================== --- pypy/dist/pypy/lang/js/reference.py (original) +++ pypy/dist/pypy/lang/js/reference.py Tue Dec 19 21:28:59 2006 @@ -6,17 +6,13 @@ self.baseobject = baseobject self.propertyname = propertyname -def get_value(v): - if not type(v, Reference): - return v - if v.baseobject is None: - raise ReferenceError - return v.baseobject.get(v.propertyname) + def GetValue(self): + if self.baseobject is None: + raise ReferenceError + return self.baseobject.Get(self.propertyname) -def put_value(v, w, context): - if not type(v, Reference): - raise ReferenceError - base = v.baseobject - if v.baseobject is None: - base = context.scope[-1] - base.put(v.propertyname, w) \ No newline at end of file + def PutValue(self, w, ctx): + base = self.baseobject + if self.baseobject is None: + base = ctx.scope[-1] + base.Put(self.propertyname, w) \ No newline at end of file Modified: pypy/dist/pypy/lang/js/test/test_interp.py ============================================================================== --- pypy/dist/pypy/lang/js/test/test_interp.py (original) +++ pypy/dist/pypy/lang/js/test/test_interp.py Tue Dec 19 21:28:59 2006 @@ -1,5 +1,4 @@ import py.test -py.test.skip("not finished yet") from pypy.lang.js.astgen import * from pypy.lang.js import interpreter @@ -34,58 +33,57 @@ def assert_prints(self, code, assval): l = [] interpreter.writer = l.append - ctx = ExecutionContext() - ctx.globals['Object'] = W_Object({}) + js_int = interpreter.Interpreter(code) try: - code.call(ctx, first = True) + js_int.run() except ThrowException, excpt: l.append("uncaught exception: "+str(excpt.exception)) assert l == assval def assert_result(self, code, result): - r = code.call() + r = code.call(ExecutionContext()) assert r.ToString() == result.ToString() def test_interp_parse(self): - self.assert_prints(parse_d("print(1+1)"), ["2"]) - self.assert_prints(parse_d("print(1+2+3); print(1)"), ["6", "1"]) - self.assert_prints(parse_d("print(1,2,3);\n"), ["1,2,3"]) + self.assert_prints("print(1+1)", ["2"]) + self.assert_prints("print(1+2+3); print(1)", ["6", "1"]) + self.assert_prints("print(1,2,3);\n", ["1,2,3"]) def test_var_assign(self): - self.assert_prints(parse_d("x=3;print(x);"), ["3"]) - self.assert_prints(parse_d("x=3;y=4;print(x+y);"), ["7"]) + self.assert_prints("x=3;print(x);", ["3"]) + self.assert_prints("x=3;y=4;print(x+y);", ["7"]) def test_string_var(self): - self.assert_prints(parse_d('print(\"sss\");'), ["sss"]) + self.assert_prints('print(\"sss\");', ["sss"]) def test_string_concat(self): - self.assert_prints(parse_d('x="xxx"; y="yyy"; print(x+y);'), ["xxxyyy"]) + self.assert_prints('x="xxx"; y="yyy"; print(x+y);', ["xxxyyy"]) def test_string_num_concat(self): - self.assert_prints(parse_d('x=4; y="x"; print(x+y, y+x);'), ["4x,x4"]) + self.assert_prints('x=4; y="x"; print(x+y, y+x);', ["4x,x4"]) def test_to_string(self): - self.assert_prints(parse_d("x={}; print(x);"), ["[object Object]"]) + self.assert_prints("x={}; print(x);", ["[object Object]"]) def test_object_access(self): - self.assert_prints(parse_d("x={d:3}; print(x.d);"), ["3"]) - self.assert_prints(parse_d("x={d:3}; print(x.d.d);"), [""]) - self.assert_prints(parse_d("x={d:3, z:4}; print(x.d+x.z);"), ["7"]) + self.assert_prints("x={d:3}; print(x.d);", ["3"]) + self.assert_prints("x={d:3}; print(x.d.d);", [""]) + self.assert_prints("x={d:3, z:4}; print(x.d+x.z);", ["7"]) def test_object_access_index(self): - self.assert_prints(parse_d('x={d:"x"}; print(x["d"]);'), ["x"]) + self.assert_prints('x={d:"x"}; print(x["d"]);', ["x"]) def test_function_prints(self): - self.assert_prints(parse_d('x=function(){print(3);}; x();'), ["3"]) + self.assert_prints('x=function(){print(3);}; x();', ["3"]) def test_function_returns(self): - self.assert_prints(parse_d('x=function(){return 1;}; print(x()+x());'), ["2"]) + self.assert_prints('x=function(){return 1;}; print(x()+x());', ["2"]) def test_var_declartion(self): - self.assert_prints(parse_d('var x = 3; print(x+x);'), ["6"]) + self.assert_prints('var x = 3; print(x+x);', ["6"]) def test_var_scoping(self): - self.assert_prints(parse_d(""" + self.assert_prints(""" var y; var p; p = 0; @@ -96,90 +94,90 @@ }; var z = 2; print(x(), y, p); - """), ["5,3,0"]) + """, ["5,3,0"]) def test_function_args(self): - self.assert_prints(parse_d(""" + self.assert_prints(""" x = function (t,r) { return t+r; }; print(x(2,3)); - """), ["5"]) + """, ["5"]) def test_function_less_args(self): - self.assert_prints(parse_d(""" + self.assert_prints(""" x = function (t, r) { return t + r; }; print(x(2)); - """), ["NaN"]) + """, ["NaN"]) def test_function_more_args(self): - self.assert_prints(parse_d(""" + self.assert_prints(""" x = function (t, r) { return t + r; }; print(x(2,3,4)); - """), ["5"]) + """, ["5"]) def test_function_has_var(self): - self.assert_prints(parse_d(""" + self.assert_prints(""" x = function () { var t = 'test'; return t; }; print(x()); - """), ["test"]) + """, ["test"]) def test_function_arguments(self): - self.assert_prints(parse_d(""" + self.assert_prints(""" x = function () { r = arguments[0]; t = arguments[1]; return t + r; }; print(x(2,3)); - """), ["5"]) + """, ["5"]) def test_index(self): - self.assert_prints(parse_d(""" + self.assert_prints(""" x = {1:"test"}; print(x[1]); - """), ["test"]) + """, ["test"]) def test_array_initializer(self): py.test.skip('not ready yet') - self.assert_prints(parse_d(""" + self.assert_prints(""" x = []; print(x); - """), ["[]"]) + """, ["[]"]) def test_throw(self): - self.assert_prints(parse_d("throw(3)"), ["uncaught exception: 3"]) + self.assert_prints("throw(3)", ["uncaught exception: 3"]) def test_group(self): - self.assert_prints(parse_d("print((2+1))"), ["3"]) + self.assert_prints("print((2+1))", ["3"]) def test_comma(self): - self.assert_prints(parse_d("print((500,3))"), ["3"]) + self.assert_prints("print((500,3))", ["3"]) def test_try_catch(self): - self.assert_prints(parse_d(""" + self.assert_prints(""" try { throw(3); } catch (x) { print(x); } - """), ["3"]) + """, ["3"]) def test_block(self): - self.assert_result(parse_d("{ 5}"), W_Number(5)) - self.assert_result(parse_d("{3; 5}"), W_Number(5)) + self.assert_result("{ 5}", W_Number(5)) + self.assert_result("{3; 5}", W_Number(5)) def test_try_catch_finally(self): - self.assert_prints(parse_d(""" + self.assert_prints(""" try { throw(3); } @@ -189,71 +187,70 @@ finally { print(5) } - """), ["3", "5"]) + """, ["3", "5"]) def test_if_then(self): - self.assert_prints(parse_d(""" + self.assert_prints(""" if (1) { print(1); } - """), ["1"]) + """, ["1"]) def test_if_then_else(self): - self.assert_prints(parse_d(""" + self.assert_prints(""" if (0) { print(1); } else { print(2); } - """), ["2"]) + """, ["2"]) def test_compare(self): - self.assert_prints(parse_d("print(1>0)"),["true"]) - self.assert_prints(parse_d("print(0>1)"),["false"]) - self.assert_prints(parse_d("print(0>0)"),["false"]) - self.assert_prints(parse_d("print(1<0)"),["false"]) - self.assert_prints(parse_d("print(0<1)"),["true"]) - self.assert_prints(parse_d("print(0<0)"),["false"]) + self.assert_prints("print(1>0)",["true"]) + self.assert_prints("print(0>1)",["false"]) + self.assert_prints("print(0>0)",["false"]) + self.assert_prints("print(1<0)",["false"]) + self.assert_prints("print(0<1)",["true"]) + self.assert_prints("print(0<0)",["false"]) def test_while(self): - self.assert_prints(parse_d(""" + self.assert_prints(""" i = 0; while (i<3) { print(i); i = i+1; } print(i); - """), ["0","1","2","3"]) + """, ["0","1","2","3"]) def test_object_creation(self): - self.assert_prints(parse_d(""" + self.assert_prints(""" o = new Object(); print(o); - """), ["[object Object]"]) + """, ["[object Object]"]) def test_new_with_function(self): - c= parse_d(""" + c= """ x = function() {this.info = 'hello';}; o = new x(); print(o.info); - """) + """ print c - self.assert_prints(c - , ["hello"]) + self.assert_prints(c, ["hello"]) def test_vars(self): - self.assert_prints(parse_d(""" - var x;x=3; print(x)"""), ["3"]) + self.assert_prints(""" + var x;x=3; print(x)""", ["3"]) def test_fun_decl(self): py.test.skip("still not ready") - self.assert_prints(parse_d(""" + self.assert_prints(""" function x () { print('i work')} x() - """), ["i work"]) + """, ["i work"]) From mwh at codespeak.net Tue Dec 19 21:51:13 2006 From: mwh at codespeak.net (mwh at codespeak.net) Date: Tue, 19 Dec 2006 21:51:13 +0100 (CET) Subject: [pypy-svn] r35905 - in pypy/dist/pypy: annotation rpython rpython/lltypesystem Message-ID: <20061219205113.EA1E31007D@code0.codespeak.net> Author: mwh Date: Tue Dec 19 21:51:12 2006 New Revision: 35905 Modified: pypy/dist/pypy/annotation/model.py pypy/dist/pypy/rpython/lltypesystem/rpbc.py pypy/dist/pypy/rpython/rpbc.py Log: attempt to avoid non-trivial char->char conversions for SmallFuncSetReprs. seems to help performance a bit, at least. Modified: pypy/dist/pypy/annotation/model.py ============================================================================== --- pypy/dist/pypy/annotation/model.py (original) +++ pypy/dist/pypy/annotation/model.py Tue Dec 19 21:51:12 2006 @@ -322,11 +322,12 @@ or a set of such instances.""" immutable = True - def __init__(self, descriptions, can_be_None=False): + def __init__(self, descriptions, can_be_None=False, subset_of=None): # descriptions is a set of Desc instances. descriptions = dict.fromkeys(descriptions) self.descriptions = descriptions self.can_be_None = can_be_None + self.subset_of = subset_of self.simplify() if self.isNone(): self.knowntype = type(None) Modified: pypy/dist/pypy/rpython/lltypesystem/rpbc.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/rpbc.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/rpbc.py Tue Dec 19 21:51:12 2006 @@ -131,13 +131,21 @@ assert len(uniquerows) == 1 self.lowleveltype = Char self.pointer_repr = FunctionsPBCRepr(rtyper, s_pbc) - self.descriptions = list(s_pbc.descriptions) - if self.s_pbc.can_be_None: - self.descriptions.insert(0, None) self._conversion_tables = {} self._dispatch_cache = {} def _setup_repr(self): + if self.s_pbc.subset_of: + assert self.s_pbc.can_be_None == self.s_pbc.subset_of.can_be_None + r = self.rtyper.getrepr(self.s_pbc.subset_of) + if r is not self: + r.setup() + self.descriptions = r.descriptions + self.c_pointer_table = r.c_pointer_table + return + self.descriptions = list(self.s_pbc.descriptions) + if self.s_pbc.can_be_None: + self.descriptions.insert(0, None) POINTER_TABLE = Array(self.pointer_repr.lowleveltype) pointer_table = malloc(POINTER_TABLE, len(self.descriptions), immortal=True) @@ -147,7 +155,6 @@ else: pointer_table[i] = self.pointer_repr.convert_const(None) self.c_pointer_table = inputconst(Ptr(POINTER_TABLE), pointer_table) - from pypy.objspace.flow import model def get_s_callable(self): return self.s_pbc @@ -192,7 +199,10 @@ graph = FunctionGraph("dispatcher", startblock, varoftype(resulttype)) row_of_graphs = self.callfamily.calltables[shape][index] links = [] - for i, desc in enumerate(self.descriptions): + descs = list(self.s_pbc.descriptions) + if self.s_pbc.can_be_None: + descs.insert(0, None) + for desc in descs: if desc is None: continue args_v = [varoftype(t) for t in argtypes] @@ -203,6 +213,7 @@ b.operations.append( SpaceOperation("direct_call", [v_fn] + args_v, v_result)) b.closeblock(Link([v_result], graph.returnblock)) + i = self.descriptions.index(desc) links.append(Link(inputargs[1:], b, chr(i))) links[-1].llexitcase = chr(i) startblock.closeblock(*links) @@ -285,11 +296,22 @@ r_from._conversion_tables[r_to] = r return r +## myf = open('convlog.txt', 'w') + class __extend__(pairtype(SmallFunctionSetPBCRepr, SmallFunctionSetPBCRepr)): def convert_from_to((r_from, r_to), v, llops): c_table = conversion_table(r_from, r_to) if c_table: assert v.concretetype is Char +## from pypy.rpython.lltypesystem.rstr import string_repr +## s = repr(llops.rtyper.annotator.annotated.get(llops.originalblock)) +## if 'LOAD_GLOBAL' in s: +## import pdb; pdb.set_trace() +## print >> myf, 'static small conv', s +## print 'static small conv', s +## llops.genop('debug_print', +## [Constant(string_repr.convert_const("dynamic small conv" + s), +## string_repr.lowleveltype)]) v_int = llops.genop('cast_char_to_int', [v], resulttype=Signed) return llops.genop('getarrayitem', [c_table, v_int], @@ -317,7 +339,7 @@ # s_func = r_func.s_pbc -- not precise enough, see # test_precise_method_call_1. Build a more precise one... funcdescs = [desc.funcdesc for desc in hop.args_s[0].descriptions] - s_func = annmodel.SomePBC(funcdescs) + s_func = annmodel.SomePBC(funcdescs, subset_of=r_func.s_pbc) v_im_self = hop.inputarg(self, arg=0) v_cls = self.r_im_self.getfield(v_im_self, '__class__', hop.llops) v_func = r_class.getclsfield(v_cls, self.methodname, hop.llops) Modified: pypy/dist/pypy/rpython/rpbc.py ============================================================================== --- pypy/dist/pypy/rpython/rpbc.py (original) +++ pypy/dist/pypy/rpython/rpbc.py Tue Dec 19 21:51:12 2006 @@ -14,6 +14,15 @@ from pypy.rpython import callparse +def small_cand(rtyper, s_pbc): + if 1 < len(s_pbc.descriptions) < rtyper.getconfig().translation.withsmallfuncsets and \ + hasattr(rtyper.type_system.rpbc, 'SmallFunctionSetPBCRepr'): + callfamily = s_pbc.descriptions.iterkeys().next().getcallfamily() + concretetable, uniquerows = get_concrete_calltable(rtyper, callfamily) + if len(uniquerows) == 1 and (not s_pbc.subset_of or small_cand(rtyper, s_pbc.subset_of)): + return True + return False + class __extend__(annmodel.SomePBC): def rtyper_makerepr(self, rtyper): if self.isNone(): @@ -27,12 +36,8 @@ getRepr = OverriddenFunctionPBCRepr else: getRepr = rtyper.type_system.rpbc.FunctionsPBCRepr - if 1 < len(self.descriptions) < rtyper.getconfig().translation.withsmallfuncsets and \ - hasattr(rtyper.type_system.rpbc, 'SmallFunctionSetPBCRepr'): - callfamily = self.descriptions.iterkeys().next().getcallfamily() - concretetable, uniquerows = get_concrete_calltable(rtyper, callfamily) - if len(uniquerows) == 1: - getRepr = rtyper.type_system.rpbc.SmallFunctionSetPBCRepr + if small_cand(rtyper, self): + getRepr = rtyper.type_system.rpbc.SmallFunctionSetPBCRepr else: getRepr = getFrozenPBCRepr elif issubclass(kind, description.ClassDesc): @@ -61,7 +66,11 @@ def rtyper_makekey(self): lst = list(self.descriptions) lst.sort() - return tuple([self.__class__, self.can_be_None]+lst) + if self.subset_of: + t = self.subset_of.rtyper_makekey() + else: + t = () + return tuple([self.__class__, self.can_be_None]+lst)+t ##builtin_descriptor_type = ( ## type(len), # type 'builtin_function_or_method' From guido at codespeak.net Tue Dec 19 22:52:29 2006 From: guido at codespeak.net (guido at codespeak.net) Date: Tue, 19 Dec 2006 22:52:29 +0100 (CET) Subject: [pypy-svn] r35906 - in pypy/dist/pypy/tool/build: . bin test Message-ID: <20061219215229.4323B10071@code0.codespeak.net> Author: guido Date: Tue Dec 19 22:52:26 2006 New Revision: 35906 Modified: pypy/dist/pypy/tool/build/bin/client pypy/dist/pypy/tool/build/bin/server pypy/dist/pypy/tool/build/client.py pypy/dist/pypy/tool/build/conftest.py pypy/dist/pypy/tool/build/server.py pypy/dist/pypy/tool/build/test/test_pypybuilder.py pypy/dist/pypy/tool/build/test/test_server.py Log: Lots of small cleanups, added some log lines, fixed problems with the additional test option (--functional), using py.code.Source instead of raw strings where appropriate, removed 'welcome' message. Also refactored the functional tests, they're a lot cleaner now. Modified: pypy/dist/pypy/tool/build/bin/client ============================================================================== --- pypy/dist/pypy/tool/build/bin/client (original) +++ pypy/dist/pypy/tool/build/bin/client Tue Dec 19 22:52:26 2006 @@ -2,69 +2,65 @@ import py from py.execnet import PopenGateway +from pypy.tool.build import outputbuffer def compile(wc, compileinfo): - code = """\ -import sys -import os -import traceback - -# interpolating the path -pypath = %r - -sys.path = [pypath] + sys.path -os.chdir(pypath) - -# nasty, interpolating a large chunk of code (OutputBuffer) -%s - -# interpolating config -compileinfo = %r - -# log locally too -log = open('/tmp/buildclient.log', 'a') -outbuffer = OutputBuffer(log) -sys.stdout = outbuffer -sys.stderr = outbuffer -try: - try: - from pypy.interpreter.error import OperationError - from pypy.translator.goal import targetpypystandalone - from pypy.translator.driver import TranslationDriver - from pypy.config import pypyoption - from pypy.tool.udir import udir - - config = pypyoption.get_pypy_config() - config.override(compileinfo) - - driver = TranslationDriver.from_targetspec( - targetpypystandalone.__dict__, config=config, - default_goal='compile') - driver.proceed(['compile']) - except Exception, e: - # XXX we may want to check - exception_occurred = True - exc, e, tb = sys.exc_info() - print '=' * 79 - print 'Exception during compilation:' - print '%%s: %%s' %% (exc, e) - print - print '\\n'.join(traceback.format_tb(tb)) - print '=' * 79 - del tb - channel.send(None) - else: - channel.send(str(udir)) -finally: - sys.stdout = sys.__stdout__ - sys.stderr = sys.__stderr__ - log.close() -channel.send(outbuffer.getvalue()) -channel.close() -""" + code = py.code.Source(outputbuffer, """\ + import sys + import os + import traceback + + # interpolating the path + pypath = %r + + sys.path = [pypath] + sys.path + os.chdir(pypath) + + # interpolating config + compileinfo = %r + + # log locally too + log = open('/tmp/buildclient.log', 'a') + outbuffer = OutputBuffer(log) + sys.stdout = outbuffer + sys.stderr = outbuffer + try: + try: + from pypy.interpreter.error import OperationError + from pypy.translator.goal import targetpypystandalone + from pypy.translator.driver import TranslationDriver + from pypy.config import pypyoption + from pypy.tool.udir import udir + + config = pypyoption.get_pypy_config() + config.override(compileinfo) + + driver = TranslationDriver.from_targetspec( + targetpypystandalone.__dict__, config=config, + default_goal='compile') + driver.proceed(['compile']) + except Exception, e: + # XXX we may want to check + exception_occurred = True + exc, e, tb = sys.exc_info() + print '=' * 79 + print 'Exception during compilation:' + print '%%s: %%s' %% (exc, e) + print + print '\\n'.join(traceback.format_tb(tb)) + print '=' * 79 + del tb + channel.send(None) + else: + channel.send(str(udir)) + finally: + sys.stdout = sys.__stdout__ + sys.stderr = sys.__stderr__ + log.close() + channel.send(outbuffer.getvalue()) + channel.close() + """) gw = PopenGateway() - buffercode = py.magic.autopath().dirpath().dirpath()\ - .join('outputbuffer.py').read() interpolated = code % (str(wc), buffercode, compileinfo) channel = gw.remote_exec(interpolated) try: Modified: pypy/dist/pypy/tool/build/bin/server ============================================================================== --- pypy/dist/pypy/tool/build/bin/server (original) +++ pypy/dist/pypy/tool/build/bin/server Tue Dec 19 22:52:26 2006 @@ -13,7 +13,7 @@ gw = PopenGateway() else: gw = SshGateway(config.server) - channel = init(gw, port=config.port, path=config.path, + channel = init(gw, port=config.port, path=config.path, projectname=config.projectname, buildpath=str(config.buildpath), mailhost=config.mailhost, @@ -29,3 +29,4 @@ finally: channel.close() gw.exit() + Modified: pypy/dist/pypy/tool/build/client.py ============================================================================== --- pypy/dist/pypy/tool/build/client.py (original) +++ pypy/dist/pypy/tool/build/client.py Tue Dec 19 22:52:26 2006 @@ -5,12 +5,12 @@ from pypy.tool.build import build class PPBClient(object): - def __init__(self, channel, sysinfo, testing=False): + def __init__(self, channel, sysinfo, testing_sleeptime=False): self.channel = channel self.sysinfo = sysinfo self.busy_on = None self.refused = [] - self.testing = testing + self.testing_sleeptime = testing_sleeptime from pypy.tool.build import ppbserver self.server = ppbserver @@ -35,7 +35,7 @@ def wait_until_done(self, request): buildpath = self.server.get_new_buildpath(request) - if not self.testing: + if not self.testing_sleeptime: fp = buildpath.zipfile.open('w') gotdata = False try: @@ -55,6 +55,11 @@ fp.close() # write the log (process stdout/stderr) to the buildpath buildpath.log = self.channel.receive() + else: + # pretend we're compiling by sleeping a bit... + open('/tmp/test_client_functional_crap', 'a').write('CLIENT - starting compile, sleeping %r secs\n' % (self.testing_sleeptime,)) + py.std.time.sleep(self.testing_sleeptime) + open('/tmp/test_client_functional_crap', 'a').write('CLIENT - done with compile\n') self.server.compilation_done(buildpath) self.busy_on = None @@ -82,7 +87,7 @@ finally: channel.close() """ -def init(gw, sysconfig, path=None, port=12321, testing=False): +def init(gw, sysconfig, path=None, port=12321, testing_sleeptime=False): from pypy.tool.build import execnetconference from pypy.config.config import make_dict @@ -91,7 +96,8 @@ sysinfo = make_dict(sysconfig) conference = execnetconference.conference(gw, port, False) - channel = conference.remote_exec(initcode % (path, sysinfo, testing)) + channel = conference.remote_exec(initcode % (path, sysinfo, + testing_sleeptime)) return channel class ChannelWrapper(object): @@ -154,7 +160,7 @@ path=config.path, port=config.port) - print channel.receive() # welcome message + print 'connected' try: try: while 1: @@ -204,7 +210,7 @@ try: print 'starting compilation' upath, log = compilefunc(svnwc, request.compileinfo) - except KeyboardInterrupt: + except (SystemExit, KeyboardInterrupt): print 'quitting...' break Modified: pypy/dist/pypy/tool/build/conftest.py ============================================================================== --- pypy/dist/pypy/tool/build/conftest.py (original) +++ pypy/dist/pypy/tool/build/conftest.py Tue Dec 19 22:52:26 2006 @@ -11,8 +11,6 @@ ), ) -py.test.pypybuilder_option = option - class Directory(Dir): def run(self): if self.fspath == mypath: Modified: pypy/dist/pypy/tool/build/server.py ============================================================================== --- pypy/dist/pypy/tool/build/server.py (original) +++ pypy/dist/pypy/tool/build/server.py Tue Dec 19 22:52:26 2006 @@ -26,18 +26,22 @@ return True class PPBServer(object): + """ the build server + + this delegates or queues build requests, and stores results and sends + out emails when they're done + """ retry_interval = 10 def __init__(self, projname, channel, builddir, mailhost=None, mailport=None, mailfrom=None): self._projname = projname self._channel = channel - self._builddir = builddir + self._buildroot = py.path.local(builddir) self._mailhost = mailhost self._mailport = mailport self._mailfrom = mailfrom - self._buildroot = py.path.local(builddir) self._clients = [] done = [] @@ -49,6 +53,7 @@ bp.remove() self._done = done + self._queued = [] # no compile client available self._waiting = [] # compilation already in progress for someone else @@ -56,10 +61,10 @@ self._namelock = thread.allocate_lock() def register(self, client): + """ register a client (instance) """ self._clients.append(client) self._channel.send('registered %s with info %r' % ( client, client.sysinfo)) - client.channel.send('welcome') def compile(self, request): """start a compilation @@ -121,7 +126,10 @@ ) accepted = client.compile(request) if accepted: + self._channel.send('compile job accepted') return True + else: + self._channel.send('compile job denied') self._channel.send( 'no suitable client available for compilation of %s' % ( request, @@ -167,6 +175,7 @@ clients = self._clients[:] for client in clients: if client.channel.isclosed(): + self._channel.send('client %s disconnected' % (client,)) if client.busy_on: self._queued.append(client.busy_on) self._clients.remove(client) @@ -282,3 +291,4 @@ mailhost, mailport, mailfrom)) return channel + Modified: pypy/dist/pypy/tool/build/test/test_pypybuilder.py ============================================================================== --- pypy/dist/pypy/tool/build/test/test_pypybuilder.py (original) +++ pypy/dist/pypy/tool/build/test/test_pypybuilder.py Tue Dec 19 22:52:26 2006 @@ -1,14 +1,26 @@ +import py +import time import path + from pypy.tool.build import client, server, execnetconference from pypy.tool.build import config from pypy.tool.build import build +from pypy.tool.build.conftest import option from pypy.config import config as pypyconfig -import py + from repo import create_temp_repo +""" some functional tests (although some of the rest aren't strictly + unit tests either), to run use --functional as an arg to py.test +""" + +# XXX this one is a bit messy, it's a quick functional test for the whole +# system, but for instance contains time.sleep()s to make sure all threads +# get the time to perform tasks and such... + # XXX NOTE: if you encounter failing tests on a slow system, you may want to # increase the sleep interval a bit to see if that helps... -SLEEP_INTERVAL = 1.0 +SLEEP_INTERVAL = 1.0 # 1 sec default, seems okay even on slow machines def _get_sysconfig(): return pypyconfig.Config( @@ -17,47 +29,46 @@ ]) ) -# some functional tests (although some of the rest aren't strictly -# unit tests either), to run use --functional as an arg to py.test -def test_functional_1(): - if not py.test.pypybuilder_option.functional: +def setup_module(mod): + if not option.functional: py.test.skip('skipping functional test, use --functional to run it') + mod.repo = repo = create_temp_repo('functional') + repo.mkdir('foo') + mod.foourl = str(repo.join('foo')) config.checkers = [] - # XXX this one is a bit messy, it's a quick functional test for the whole - # system, but for instance contains time.sleep()s to make sure all threads - # get the time to perform tasks and such... - - repo = create_temp_repo('functional') - repo.mkdir('foo') - foourl = str(repo.join('foo')) + mod.sgw = sgw = py.execnet.PopenGateway() + mod.temppath = temppath = py.test.ensuretemp('pypybuilder-functional') - # first initialize a server - sgw = py.execnet.PopenGateway() - temppath = py.test.ensuretemp('pypybuilder-functional') - sc = server.init(sgw, port=config.testport, path=config.testpath, + mod.sc = sc = server.init(sgw, port=config.testport, path=config.testpath, buildpath=str(temppath)) - # give the server some time to wake up - py.std.time.sleep(SLEEP_INTERVAL) + def read(): + while 1: + try: + print sc.receive() + except EOFError: + break + py.std.thread.start_new_thread(read, ()) - # then two clients, both with different system info - sysconfig1 = _get_sysconfig() - cgw1 = py.execnet.PopenGateway() - cc1 = client.init(cgw1, sysconfig1, port=config.testport, testing=True) - cc1.receive() # welcome message - - sysconfig2 = _get_sysconfig() - sysconfig2.foo = 2 - cgw2 = py.execnet.PopenGateway() - cc2 = client.init(cgw2, sysconfig2, port=config.testport, testing=True) - cc2.receive() # welcome message + # give the server some time to wake up + time.sleep(SLEEP_INTERVAL) - # give the clients some time to register themselves - py.std.time.sleep(SLEEP_INTERVAL) +def teardown_module(mod): + mod.sc.close() + mod.sgw.exit() + +def create_client_channel(**conf): + cgw = py.execnet.PopenGateway() + sysconfig = _get_sysconfig() + sysconfig.__dict__.update(conf) + channel = client.init(cgw, sysconfig, port=config.testport, + testing_sleeptime=SLEEP_INTERVAL * 4) + channel.send(True) + return cgw, channel - # now we're going to send some compile jobs +def compile(**sysconfig): code = """ import sys sys.path += %r @@ -67,101 +78,112 @@ channel.send(ppbserver.compile(%r)) channel.close() """ - compgw = py.execnet.PopenGateway() - compconf = execnetconference.conference(compgw, config.testport) - - # we're going to have to closely mimic the bin/client script to avoid - # freezes (from the app waiting for input) - - # this one should fail because there's no client found for foo = 3 - br = build.BuildRequest('foo1 at bar.com', {'foo': 3}, {}, foourl, - 1, 0) - compc = compconf.remote_exec(code % (config.testpath, br)) - - # sorry... - py.std.time.sleep(SLEEP_INTERVAL) - - ret = compc.receive() - assert not ret[0] - assert ret[1].find('no suitable client found') > -1 - - # this one should be handled by client 1 - br = build.BuildRequest('foo2 at bar.com', {'foo': 1}, {}, foourl, - 1, 0) - compc = compconf.remote_exec(code % (config.testpath, br)) - - # client 1 will now send a True to the server to tell it wants to compile - cc1.send(True) - - # and another one - py.std.time.sleep(SLEEP_INTERVAL) - - ret = compc.receive() - print repr(ret) - assert not ret[0] - assert ret[1].find('found a suitable client') > -1 - - # the messages may take a bit to arrive, too - py.std.time.sleep(SLEEP_INTERVAL) - - # client 1 should by now have received the info to build for - ret = cc1.receive() - request = build.BuildRequest.fromstring(ret) - assert request.sysinfo == {'foo': 1} - - # this should have created a package in the temp dir - assert len(temppath.listdir()) == 1 - - # now we're going to satisfy the first request by adding a new client - sysconfig3 = _get_sysconfig() - sysconfig3.foo = 3 - cgw3 = py.execnet.PopenGateway() - cc3 = client.init(cgw3, sysconfig3, port=config.testport, testing=True) + gw = py.execnet.PopenGateway() + conf = execnetconference.conference(gw, config.testport) - # add True to the buffer just like we did for channels 1 and 2 - cc3.send(True) + try: + br = build.BuildRequest('foo at bar.com', sysconfig, {}, foourl, 1, 0) + channel = conf.remote_exec(code % (config.testpath, br)) + try: + # sorry... + time.sleep(SLEEP_INTERVAL) + ret = channel.receive() + finally: + channel.close() + finally: + gw.exit() - # again a bit of waiting may be desired - py.std.time.sleep(SLEEP_INTERVAL) + return ret - # _try_queued() should check whether there are new clients available for - # queued jobs - code = """ +def get_info(attr): + code = py.code.Source(""" import sys, time sys.path += %r from pypy.tool.build import ppbserver + ppbserver._cleanup_clients() + ppbserver._test_waiting() ppbserver._try_queued() - # give the server some time, the clients 'compile' in threads - time.sleep(%s) - channel.send(ppbserver._waiting) - channel.close() - """ - compgw2 = py.execnet.PopenGateway() - compconf2 = execnetconference.conference(compgw2, config.testport) - compc2 = compconf2.remote_exec(code % (config.testpath, SLEEP_INTERVAL)) - cc2.send(True) + # take some time to update all the lists + time.sleep(%s) + + data = [str(x) for x in ppbserver.%s] + channel.send(data) + channel.close() + """ % (config.testpath, SLEEP_INTERVAL, attr)) + gw = py.execnet.PopenGateway() + try: + cf = execnetconference.conference(gw, config.testport) + channel = cf.remote_exec(code) + try: + ret = channel.receive() + finally: + channel.close() + finally: + gw.exit() + return ret + +def test_functional(): + # first we check if the queues are empty + queued = get_info('_queued') + assert len(queued) == 0 + waiting = get_info('_waiting') + assert len(waiting) == 0 + clients = get_info('_clients') + assert len(clients) == 0 + + # then we request a compilation for sysinfo foo=1, obviously this can not + # be fulfilled yet + ispath, data = compile(foo=1) + assert not ispath + assert 'no suitable client' in data + queued = get_info('_queued') + assert len(queued) == 1 + + # now we register a client with the same sysinfo, note that we don't tell + # the server yet that the client actually accepts to handle the request + gw, cchannel = create_client_channel(foo=1) + try: + clients = get_info('_clients') + assert len(clients) == 1 + + # XXX quite a bit scary here, the client will take exactly + # 4 * SLEEP_INTERVAL seconds to fake the compilation... here we should + # (if all is well) still be compiling + + ispath, data = compile(foo=1) + assert not ispath + assert 'in progress' in data + + waiting = get_info('_waiting') + assert len(waiting) == 1 + + # this sleep, along with that in the previous compile call, should be + # enough to reach the end of fake compilation + time.sleep(SLEEP_INTERVAL * 3) + + # both the jobs should have been done now... + queued = get_info('_queued') + assert len(queued) == 0 + + waiting = get_info('_waiting') + assert len(waiting) == 0 + + # now a new request for the same build should return in a path being + # returned + ispath, data = compile(foo=1) + assert ispath + + queued = get_info('_queued') + assert len(queued) == 0 + waiting = get_info('_waiting') + assert len(waiting) == 0 + + finally: + cchannel.close() + gw.exit() - # we check whether all emails are now sent, since after adding the third - # client, and calling _try_queued(), both jobs should have been processed - ret = compc2.receive() - assert ret == [] - - # this should also have created another package in the temp dir - assert len(temppath.listdir()) == 2 - - # some cleanup (this should all be in nested try/finallys, blegh) - cc1.close() - cc2.close() - cc3.close() - compc.close() - compc2.close() - sc.close() - - cgw1.exit() - cgw2.exit() - compgw.exit() - compgw2.exit() - sgw.exit() + clients = get_info('_clients') + assert len(clients) == 0 Modified: pypy/dist/pypy/tool/build/test/test_server.py ============================================================================== --- pypy/dist/pypy/tool/build/test/test_server.py (original) +++ pypy/dist/pypy/tool/build/test/test_server.py Tue Dec 19 22:52:26 2006 @@ -36,8 +36,6 @@ assert svr._clients[0] == c1 assert svr._clients[1] == c2 - assert c1.channel.receive() == 'welcome' - assert c2.channel.receive() == 'welcome' py.test.raises(IndexError, "c1.channel.receive()") assert svr._channel.receive().find('registered') > -1 From arigo at codespeak.net Wed Dec 20 01:15:50 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 20 Dec 2006 01:15:50 +0100 (CET) Subject: [pypy-svn] r35907 - pypy/extradoc/sprintinfo/leysin-winter-2007 Message-ID: <20061220001550.5D6D910071@code0.codespeak.net> Author: arigo Date: Wed Dec 20 01:15:48 2006 New Revision: 35907 Modified: pypy/extradoc/sprintinfo/leysin-winter-2007/people.txt Log: - fix Maciek's arrival date - add Laura & Jacob Modified: pypy/extradoc/sprintinfo/leysin-winter-2007/people.txt ============================================================================== --- pypy/extradoc/sprintinfo/leysin-winter-2007/people.txt (original) +++ pypy/extradoc/sprintinfo/leysin-winter-2007/people.txt Wed Dec 20 01:15:48 2006 @@ -19,8 +19,10 @@ Michael Hudson 7th-15th Ermina Niko Matsakis 9th-14th Ermina Antonio Cuni 7th-15th Ermina -Maciej Fijalkowski 5th?-17th? Ermina +Maciej Fijalkowski 6th-17th? Ermina Eric van Riet Paap 10th?-14th? Ermina +Jacob Hallen 5th-15th Ermina +Laura Creighton 5th-15th Ermina ==================== ============== ===================== People on the following list were present at previous sprints: @@ -32,7 +34,6 @@ Christian Tismer ? ? Michael Hudson ? ? Anders Lehmann ? ? -Jacob Hallen ? ? Niklaus Haldimann ? ? Aurelien Campeas ? ? Alexandre Fayolle ? ? @@ -42,7 +43,6 @@ Boris Feigin ? ? Andrew Thompson ? ? Bert Freudenberg ? ? -Laura Creighton ? ? Beatrice Duering ? ? Carl Friedrich Bolz ? ? Richard Emslie ? ? From santagada at codespeak.net Wed Dec 20 02:28:08 2006 From: santagada at codespeak.net (santagada at codespeak.net) Date: Wed, 20 Dec 2006 02:28:08 +0100 (CET) Subject: [pypy-svn] r35910 - in pypy/dist/pypy/lang/js: . test Message-ID: <20061220012808.5E65F1007D@code0.codespeak.net> Author: santagada Date: Wed Dec 20 02:27:52 2006 New Revision: 35910 Removed: pypy/dist/pypy/lang/js/context.py Modified: pypy/dist/pypy/lang/js/astgen.py pypy/dist/pypy/lang/js/interpreter.py pypy/dist/pypy/lang/js/jsobj.py pypy/dist/pypy/lang/js/reference.py pypy/dist/pypy/lang/js/test/test_interp.py Log: 24 of 32 test passing, and a lot less hacks Modified: pypy/dist/pypy/lang/js/astgen.py ============================================================================== --- pypy/dist/pypy/lang/js/astgen.py (original) +++ pypy/dist/pypy/lang/js/astgen.py Wed Dec 20 02:27:52 2006 @@ -1,8 +1,6 @@ from pypy.annotation.pairtype import extendabletype -from pypy.lang.js.context import ExecutionContext -from pypy.lang.js.jsobj import W_Object, w_Undefined -from pypy.lang.js.scope import scope_manager +from pypy.lang.js.jsobj import W_Object, w_Undefined, ExecutionContext class Node(object): __metaclass__ = extendabletype @@ -47,11 +45,10 @@ self.right = right class Function(Node): - def __init__(self, name, params, body, scope): + def __init__(self, name, params, body): self.name = name self.params = params self.body = body - self.scope = scope class Group(Node): def __init__(self, expr): @@ -107,8 +104,6 @@ class Script(Node): def __init__(self, nodes, var_decl, func_decl): self.nodes = nodes - [scope_manager.add_variable(id.name, w_Undefined) for id in var_decl] - [scope_manager.add_variable(id.name, id) for id in func_decl] self.var_decl = var_decl self.func_decl = func_decl @@ -190,14 +185,12 @@ return Dot(from_dict(d['0']), from_dict(d['1'])) elif tp == 'FUNCTION': name = d.get('name', '') - scope = scope_manager.enter_scope() body = from_dict(d['body']) if d['params'] == '': params = [] else: params = d['params'].split(',') - f = Function(name, params, body, scope) - scope_manager.leave_scope() + f = Function(name, params, body) return f elif tp == 'GROUP': return Group(from_dict(d['0'])) Modified: pypy/dist/pypy/lang/js/interpreter.py ============================================================================== --- pypy/dist/pypy/lang/js/interpreter.py (original) +++ pypy/dist/pypy/lang/js/interpreter.py Wed Dec 20 02:27:52 2006 @@ -1,9 +1,7 @@ from pypy.lang.js.astgen import * from pypy.lang.js.jsparser import parse -from pypy.lang.js.context import * -from pypy.lang.js.jsobj import W_Number, W_String, W_Object -from pypy.lang.js.jsobj import w_Undefined, W_Arguments, W_Boolean, NaN +from pypy.lang.js.jsobj import * def writer(x): print x @@ -41,7 +39,7 @@ class __extend__(Array): - def call(self, context): + def call(self, ctx): d = dict(enumerate(self.items)) return W_Array(d) @@ -53,85 +51,80 @@ return v3 class __extend__(Block): - def call(self, context): + def call(self, ctx): try: last = w_Undefined for node in self.nodes: - last = node.call(context) + last = node.call(ctx) return last except ExecutionReturned, e: return e.value class __extend__(Call): - def call(self, context): + def call(self, ctx): name = self.identifier.get_literal() if name == 'print': - writer(",".join([i.GetValue().ToString() for i in self.arglist.call(context)])) - else: - backup_scope = scope_manager.current_scope - - w_obj = context.access(name) - scope_manager.current_scope = w_obj.function.scope - - retval = w_obj.Call(context=context, args=[i for i in self.arglist.call(context)]) - scope_manager.current_scope = backup_scope + writer(",".join([i.GetValue().ToString() for i in self.arglist.call(ctx)])) + else: + w_obj = ctx.resolve_identifier(name).GetValue() + retval = w_obj.Call(ctx=ctx, args=[i for i in self.arglist.call(ctx)]) return retval class __extend__(Comma): - def call(self, context): - self.left.call(context) - return self.right.call(context) + def call(self, ctx): + self.left.call(ctx) + return self.right.call(ctx) class __extend__(Dot): - def call(self, context=None): - w_obj = self.left.call(context).GetValue().ToObject() + def call(self, ctx=None): + w_obj = self.left.call(ctx).GetValue().ToObject() name = self.right.get_literal() return w_obj.Get(name) - def put(self, context, val): + def put(self, ctx, val): print self.left.name, self.right.name, val if isinstance(self.left,Identifier): - obj = context.access(self.left.name) + obj = ctx.access(self.left.name) print obj.Class obj.dict_w[self.right.name] = val elif isinstance(self.left,Dot): - obj = self.left.put(context, val) + obj = self.left.put(ctx, val) return obj - #w_obj = self.left.put(context).GetValue().ToObject() + #w_obj = self.left.put(ctx).GetValue().ToObject() #name = self.right.get_literal() #w_obj.dict_w[self.name] = val class __extend__(Function): - def call(self, context): - w_obj = W_Object({}, function=self) + def call(self, ctx): + w_obj = W_FunctionObject(self, ctx) return w_obj class __extend__(Identifier): def call(self, ctx): - # if self.initialiser is not None: - # context.assign(self.name, self.initialiser.call(context)) - value = ctx.resolve_identifier(self.name) - return value + if self.initialiser is not None: + ref = ctx.resolve_identifier(self.name) + ref.PutValue(self.initialiser.call(ctx), ctx) + return ctx.resolve_identifier(self.name) - def put(self, context, val, obj=None): - context.assign(self.name, val) + def put(self, ctx, val, obj=None): + ctx.assign(self.name, val) def get_literal(self): return self.name class __extend__(If): - def call(self, context=None): - if self.condition.call(context).ToBoolean(): - return self.thenPart.call(context) + def call(self, ctx=None): + if self.condition.call(ctx).ToBoolean(): + return self.thenPart.call(ctx) else: - return self.elsePart.call(context) + return self.elsePart.call(ctx) class __extend__(Group): - def call(self, context = None): - return self.expr.call(context) + def call(self, ctx = None): + return self.expr.call(ctx) def ARC(x, y): """ @@ -154,9 +147,9 @@ pass class __extend__(Gt): - def call(self, context = None): - s2 = self.left.call(context).GetValue() - s4 = self.right.call(context).GetValue() + def call(self, ctx = None): + s2 = self.left.call(ctx).GetValue() + s4 = self.right.call(ctx).GetValue() s5 = ARC(s4, s2) if s5 is None: return W_Boolean(False) @@ -164,9 +157,9 @@ return W_Boolean(s5) class __extend__(Lt): - def call(self, context = None): - s2 = self.left.call(context).GetValue() - s4 = self.right.call(context).GetValue() + def call(self, ctx = None): + s2 = self.left.call(ctx).GetValue() + s4 = self.right.call(ctx).GetValue() s5 = ARC(s2, s4) if s5 is None: return W_Boolean(False) @@ -174,34 +167,30 @@ return W_Boolean(s5) class __extend__(Index): - def call(self, context=None): - w_obj = self.left.call(context).GetValue() - w_member = self.expr.call(context).GetValue() + def call(self, ctx=None): + w_obj = self.left.call(ctx).GetValue() + w_member = self.expr.call(ctx).GetValue() w_obj = w_obj.ToObject() name = w_member.ToString() return w_obj.Get(name) class __extend__(List): - def call(self, context=None): - return [node.call(context) for node in self.nodes] + def call(self, ctx): + return [node.call(ctx) for node in self.nodes] class __extend__(New): - def call(self, context=None): - try: - constructor = context.access(self.identifier) - except NameError: - constructor = scope_manager.get_variable(self.identifier) - obj = W_Object({}) - obj.Class = 'Object' + def call(self, ctx=None): + obj = W_Object() #it should be undefined... to be completed - obj.dict_w['prototype'] = constructor.dict_w['prototype'] - constructor.Call(context, this = obj) + constructor = ctx.resolve_identifier(self.identifier).GetValue() + obj.Put('prototype', constructor.Get('prototype')) + constructor.Call(ctx, this = obj) return obj class __extend__(Number): - def call(self, context): + def call(self, ctx): return W_Number(self.num) def get_literal(self): @@ -209,18 +198,19 @@ return str(W_Number(self.num)) class __extend__(ObjectInit): - def call(self, context=None): - w_obj = W_Object({}) + def call(self, ctx): + w_obj = W_Object() for property in self.properties: name = property.name.get_literal() - w_expr = property.value.call(context).GetValue() + w_expr = property.value.call(ctx).GetValue() w_obj.Put(name, w_expr) return w_obj class __extend__(Plus): - def call(self, context=None): - left = self.left.call(context).GetValue() - right = self.right.call(context).GetValue() + def call(self, ctx): + print "left", self.left.call(ctx) + left = self.left.call(ctx).GetValue() + right = self.right.call(ctx).GetValue() prim_left = left.ToPrimitive('Number') prim_right = right.ToPrimitive('Number') # INSANE @@ -236,25 +226,9 @@ class __extend__(Script): def call(self, ctx): - # ncontext = ExecutionContext(context) - # for i, item in enumerate(params): - # try: - # temp = args[i] - # except IndexError: - # temp = w_Undefined - # ncontext.assign(item, temp) - # - # for var in self.var_decl: - # if first: - # ncontext.globals[var.name] = w_Undefined - # else: - # ncontext.locals[var.name] = w_Undefined - - # w_Arguments = W_Arguments(dict([(str(x),y) for x,y in enumerate(args)])) - # ncontext.assign('arguments', w_Arguments) - # - # ncontext.assign('this', this) - + for var in self.var_decl: + ctx.variable.Put(var.name, w_Undefined) + try: last = w_Undefined for node in self.nodes: @@ -264,38 +238,38 @@ return e.value class __extend__(Semicolon): - def call(self, context=None): - return self.expr.call(context) + def call(self, ctx=None): + return self.expr.call(ctx) class __extend__(String): - def call(self, context=None): + def call(self, ctx=None): return W_String(self.strval) def get_literal(self): return self.strval class __extend__(Return): - def call(self, context=None): - raise ExecutionReturned(self.expr.call(context)) + def call(self, ctx): + raise ExecutionReturned(self.expr.call(ctx)) class __extend__(Throw): - def call(self, context=None): - raise ThrowException(self.exception.call(context)) + def call(self, ctx): + raise ThrowException(self.exception.call(ctx)) class __extend__(Try): - def call(self, context=None): + def call(self, ctx): e = None try: - tryresult = self.tryblock.call(context) + tryresult = self.tryblock.call(ctx) except ThrowException, excpt: e = excpt - ncontext = ExecutionContext(context) - ncontext.assign(self.catchparam, e.exception) + nctx = ExecutionContext(ctx) + nctx.assign(self.catchparam, e.exception) if self.catchblock is not None: - tryresult = self.catchblock.call(ncontext) + tryresult = self.catchblock.call(nctx) if self.finallyblock is not None: - tryresult = self.finallyblock.call(context) + tryresult = self.finallyblock.call(ctx) #if there is no catchblock reraise the exception if (e is not None) and (self.catchblock is None): @@ -309,7 +283,9 @@ class __extend__(Vars): def call(self, ctx): + print self.nodes for var in self.nodes: + print var.name var.call(ctx) class __extend__(While): Modified: pypy/dist/pypy/lang/js/jsobj.py ============================================================================== --- pypy/dist/pypy/lang/js/jsobj.py (original) +++ pypy/dist/pypy/lang/js/jsobj.py Wed Dec 20 02:27:52 2006 @@ -1,3 +1,6 @@ +# encoding: utf-8 + +from pypy.lang.js.reference import Reference class SeePage(NotImplementedError): pass @@ -30,7 +33,7 @@ return self def ToString(self): - return str(self) + return '' def ToObject(self): return self @@ -39,40 +42,31 @@ return NaN def __repr__(self): - return "<%s(%s)>" % (self.__class__.__name__, str(self)) + return "<%s(%s)>" % (self.__class__.__name__, self.ToString()) class W_Primitive(W_Root): """unifying parent for primitives""" def ToPrimitive(self, PreferredType): return self - - class W_Object(W_Root): - def __init__(self, function=None): + def __init__(self): self.propdict = {} self.propdict['toString'] = Property('toString', - W_Builtin(self.__str__)) # FIXME: Not working + W_Builtin(self.__str__)) self.propdict['prototype'] = Property('prototype', w_Undefined, DontDelete=True) self.Prototype = None self.Class = "Object" - self.function = function self.scope = [] - def Call(self, context, args=[], this = None): # FIXME: Context-ng - if self.function is not none: - return self.function.body.call(context=context, args=args, - params=self.function.params, - this=this) - else: - print "returning common object" - return W_Object() + def Call(self, ctx, args=[], this = None): + return W_Object() def Get(self, P): if P in self.propdict: return self.propdict[P].value - if self.prototype is None: return w_Undefined - return self.prototype.Get(P) # go down the prototype chain + if self.Prototype is None: return w_Undefined + return self.Prototype.Get(P) # go down the prototype chain def CanPut(self, P): if P in self.propdict: @@ -121,18 +115,49 @@ ToPrimitive = DefaultValue - def __str__(self): + def ToString(self): return "[object %s]"%(self.Class,) class W_Arguments(W_Object): - pass + def __init__(self, callee, args): + W_Object.__init__(self) + self.Put('callee', callee) + self.Put('length', len(args)) + for i, arg in enumerate(args): + self.Put(str(i), arg) class ActivationObject(W_Object): """The object used on function calls to hold arguments and this""" def __init__(self): - W_Object.__init__() - self.propdict.pop(P) - + W_Object.__init__(self) + self.propdict.pop("toString") + self.propdict.pop("prototype") + +class W_FunctionObject(W_Object): + def __init__(self, function, ctx): + # TODO: See page 80 + W_Object.__init__(self) + self.function = function + self.Class = "Function" + self.Prototype = None # TODO: See page 95 section 15.3.3.1 + self.scope = ctx.scope[:] + + def Call(self, ctx, args=[], this=None): + print args + act = ActivationObject() + for i, arg in enumerate(args): + try: + value = args[i] + except IndexError: + value = w_Undefined + act.Put(self.function.params[i], value) + act.Put('this', this) + print act.propdict + w_Arguments = W_Arguments(self, args) + act.Put('arguments', w_Arguments) + newctx = function_context(self.scope, act, this) + val = self.function.body.call(ctx=newctx) + return val class W_Undefined(W_Root): def __str__(self): @@ -173,12 +198,16 @@ def __str__(self): return self.strval + def ToString(self): + return self.strval + def ToBoolean(self): return bool(self.strval) class W_Number(W_Primitive): def __init__(self, floatval): + print "novo numero" self.floatval = floatval def ToString(self): @@ -223,4 +252,66 @@ w_Undefined = W_Undefined() w_Null = W_Null() +class ExecutionContext(object): + def __init__(self): + self.scope = [] + self.this = None + self.variable = None + self.property = Property('',w_Undefined) #Attribute flags for new vars + + def assign(self, name, value): + """ + assign to property name, creating it if it doesn't exist + """ + pass + #ref = self.resolve_identifier(name) + #if ref. + + def get_global(self): + return self.scope[-1] + + def push_object(self, obj): + """push object into scope stack""" + self.scope.insert(0, obj) + self.variable = obj + + def pop_object(self): + """docstring for pop_object""" + return self.scope.pop(0) + + def resolve_identifier(self, identifier): + for obj in self.scope: + if obj.HasProperty(identifier): + return Reference(identifier, obj) + + return Reference(identifier) + + +def global_context(w_global): + ctx = ExecutionContext() + ctx.push_object(w_global) + ctx.this = w_global + ctx.property = Property('', w_Undefined, DontDelete=True) + return ctx + +def function_context(scope, activation, this=None): + ctx = ExecutionContext() + ctx.scope = scope + ctx.push_object(activation) + if this is None: + ctx.this = ctx.get_global() + else: + ctx.this = this + + ctx.property = Property('', w_Undefined, DontDelete=True) + return ctx + +def eval_context(calling_context): + ctx = ExecutionContext() + ctx.scope = calling_context.scope[:] + ctx.this = calling_context.this + ctx.variable = calling_context.variable + ctx.property = Property('', w_Undefined) + return ctx + \ No newline at end of file Modified: pypy/dist/pypy/lang/js/reference.py ============================================================================== --- pypy/dist/pypy/lang/js/reference.py (original) +++ pypy/dist/pypy/lang/js/reference.py Wed Dec 20 02:27:52 2006 @@ -15,4 +15,7 @@ base = self.baseobject if self.baseobject is None: base = ctx.scope[-1] - base.Put(self.propertyname, w) \ No newline at end of file + base.Put(self.propertyname, w) + + def __str__(self): + return str(self.baseobject) + " : " + str(self.propertyname) \ No newline at end of file Modified: pypy/dist/pypy/lang/js/test/test_interp.py ============================================================================== --- pypy/dist/pypy/lang/js/test/test_interp.py (original) +++ pypy/dist/pypy/lang/js/test/test_interp.py Wed Dec 20 02:27:52 2006 @@ -1,14 +1,14 @@ + +import sys +from StringIO import StringIO + import py.test from pypy.lang.js.astgen import * from pypy.lang.js import interpreter from pypy.lang.js.jsparser import parse from pypy.lang.js.interpreter import ThrowException -from pypy.lang.js.jsobj import W_Number, W_Object -from pypy.lang.js.context import ExecutionContext - -import sys -from StringIO import StringIO +from pypy.lang.js.jsobj import W_Number, W_Object, ExecutionContext def js_is_on_path(): @@ -21,7 +21,7 @@ class TestInterp(object): def test_simple(self): - assert Plus(Number(3), Number(4)).call().floatval == 7 + assert Plus(Number(3), Number(4)).call(ExecutionContext()).floatval == 7 # s = Script([Semicolon(Plus(Number(3), Number(4)))], [], []) # s.call() l = [] @@ -79,8 +79,10 @@ def test_function_returns(self): self.assert_prints('x=function(){return 1;}; print(x()+x());', ["2"]) - def test_var_declartion(self): + def test_var_declaration(self): + self.assert_prints('var x = 3; print(x);', ["3"]) self.assert_prints('var x = 3; print(x+x);', ["6"]) + def test_var_scoping(self): self.assert_prints(""" From mwh at codespeak.net Wed Dec 20 09:50:56 2006 From: mwh at codespeak.net (mwh at codespeak.net) Date: Wed, 20 Dec 2006 09:50:56 +0100 (CET) Subject: [pypy-svn] r35911 - pypy/dist/pypy/objspace/cpy Message-ID: <20061220085056.BA0981007E@code0.codespeak.net> Author: mwh Date: Wed Dec 20 09:50:54 2006 New Revision: 35911 Modified: pypy/dist/pypy/objspace/cpy/objspace.py Log: add the track_builtin_shadowing keyword argument to the CPyObjSpace's newdict(), fixes a bunch of tests that failed overnight. Modified: pypy/dist/pypy/objspace/cpy/objspace.py ============================================================================== --- pypy/dist/pypy/objspace/cpy/objspace.py (original) +++ pypy/dist/pypy/objspace/cpy/objspace.py Wed Dec 20 09:50:54 2006 @@ -199,7 +199,7 @@ def newfloat(self, floatval): return PyFloat_FromDouble(floatval) - def newdict(self): + def newdict(self, track_builtin_shadowing=False): return PyDict_New() def newlist(self, items_w): From ac at codespeak.net Wed Dec 20 12:03:58 2006 From: ac at codespeak.net (ac at codespeak.net) Date: Wed, 20 Dec 2006 12:03:58 +0100 (CET) Subject: [pypy-svn] r35912 - pypy/dist/pypy/jit/codegen/i386 Message-ID: <20061220110358.316AC1007E@code0.codespeak.net> Author: ac Date: Wed Dec 20 12:03:57 2006 New Revision: 35912 Modified: pypy/dist/pypy/jit/codegen/i386/codebuf.py Log: (pedronis, arre) Oops, missing method. Modified: pypy/dist/pypy/jit/codegen/i386/codebuf.py ============================================================================== --- pypy/dist/pypy/jit/codegen/i386/codebuf.py (original) +++ pypy/dist/pypy/jit/codegen/i386/codebuf.py Wed Dec 20 12:03:57 2006 @@ -160,6 +160,9 @@ def tell(self): return self._base + 2 * self._pos + def seekback(self, count): + self._pos -= count + def done(self): pass From cfbolz at codespeak.net Wed Dec 20 12:15:50 2006 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Wed, 20 Dec 2006 12:15:50 +0100 (CET) Subject: [pypy-svn] r35913 - in pypy/dist/pypy: lang/prolog/interpreter rlib/parsing rlib/parsing/test Message-ID: <20061220111550.C6E221007E@code0.codespeak.net> Author: cfbolz Date: Wed Dec 20 12:15:45 2006 New Revision: 35913 Modified: pypy/dist/pypy/lang/prolog/interpreter/parsing.py pypy/dist/pypy/rlib/parsing/deterministic.py pypy/dist/pypy/rlib/parsing/lexer.py pypy/dist/pypy/rlib/parsing/parsing.py pypy/dist/pypy/rlib/parsing/test/pygrammar.txt pypy/dist/pypy/rlib/parsing/test/test_lexer.py pypy/dist/pypy/rlib/parsing/test/test_parse.py pypy/dist/pypy/rlib/parsing/test/test_pythonparse.py pypy/dist/pypy/rlib/parsing/test/test_translate.py Log: use a instances of a Token and SourcePos class instead of tuples everywhere. small changes to the experimental python grammar. Modified: pypy/dist/pypy/lang/prolog/interpreter/parsing.py ============================================================================== --- pypy/dist/pypy/lang/prolog/interpreter/parsing.py (original) +++ pypy/dist/pypy/lang/prolog/interpreter/parsing.py Wed Dec 20 12:15:45 2006 @@ -151,9 +151,9 @@ class PrologParseTable(LazyParseTable): def terminal_equality(self, symbol, input): - if input[0] == "ATOM": - return symbol == "ATOM" or symbol == input[1] - return symbol == input[0] + if input.name == "ATOM": + return symbol == "ATOM" or symbol == input.source + return symbol == input.name class PrologPackratParser(PackratParser): def __init__(self, rules, startsymbol): @@ -191,7 +191,7 @@ line = [] for tok in tokens: line.append(tok) - if tok[0] == ".": + if tok.name == ".": lines.append(line) line = [] if parser is None: Modified: pypy/dist/pypy/rlib/parsing/deterministic.py ============================================================================== --- pypy/dist/pypy/rlib/parsing/deterministic.py (original) +++ pypy/dist/pypy/rlib/parsing/deterministic.py Wed Dec 20 12:15:45 2006 @@ -21,18 +21,16 @@ return real_result class LexerError(Exception): - def __init__(self, input, state, index, lineno=-1, columnno=-1): + def __init__(self, input, state, source_pos): self.input = input self.state = state - self.index = index - self.lineno = lineno - self.columnno = columnno - self.args = (input, state, index, lineno, columnno) + self.source_pos = source_pos + self.args = (input, state, source_pos) def nice_error_message(self, filename=""): - result = [" File %s, line %s" % (filename, self.lineno)] - result.append(self.input.split("\n")[self.lineno]) - result.append(" " * self.columnno + "^") + result = [" File %s, line %s" % (filename, self.source_pos.lineno)] + result.append(self.input.split("\n")[self.source_pos.lineno]) + result.append(" " * self.source_pos.columnno + "^") result.append("LexerError") return "\n".join(result) Modified: pypy/dist/pypy/rlib/parsing/lexer.py ============================================================================== --- pypy/dist/pypy/rlib/parsing/lexer.py (original) +++ pypy/dist/pypy/rlib/parsing/lexer.py Wed Dec 20 12:15:45 2006 @@ -2,6 +2,40 @@ from pypy.rlib.objectmodel import we_are_translated from pypy.rlib.parsing import deterministic, regex +class Token(object): + def __init__(self, name, source, source_pos): + self.name = name + self.source = source + self.source_pos = source_pos + + def __eq__(self, other): + # for testing only + return self.__dict__ == other.__dict__ + + def __ne__(self, other): + # for testing only + return not self == other + + def __repr__(self): + return "Token(%r, %r, %r)" % (self.name, self.source, self.source_pos) + +class SourcePos(object): + def __init__(self, i, lineno, columnno): + self.i = i + self.lineno = lineno + self.columnno = columnno + + def __eq__(self, other): + # for testing only + return self.__dict__ == other.__dict__ + + def __ne__(self, other): + # for testing only + return not self == other + + def __repr__(self): + return "SourcePos(%r, %r, %r)" % (self.i, self.lineno, self.columnno) + class Lexer(object): def __init__(self, token_regexs, names, ignore=None): self.token_regexs = token_regexs @@ -78,7 +112,8 @@ if i == len(self.text): if self.eof: self.last_matched_index += 1 - return ("EOF", "EOF", i, self.lineno, self.columnno) + return Token("EOF", "EOF", + SourcePos(i, self.lineno, self.columnno)) else: raise StopIteration if i >= len(self.text) + 1: @@ -87,30 +122,33 @@ if i < 0: i = ~i if start == self.last_matched_index + 1: - raise deterministic.LexerError(self.text, self.state, i - 1, - lineno=self.lineno, - columnno=self.columnno) + source_pos = SourcePos(i - 1, self.lineno, self.columnno) + raise deterministic.LexerError(self.text, self.state, + source_pos) stop = self.last_matched_index + 1 assert stop >= 0 - token = self.text[start: stop] - lineno, columnno = self.adjust_position(token) + source = self.text[start: stop] + lineno, columnno = self.adjust_position(source) if self.automaton.names[self.last_matched_state] in self.ignore: continue - return (self.automaton.names[self.last_matched_state], - token, start, lineno, columnno) + source_pos = SourcePos(start, lineno, columnno) + return Token(self.automaton.names[self.last_matched_state], + source, source_pos) 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: if self.eof: self.last_matched_index += 1 - return ("EOF", "EOF", i, self.lineno, self.columnno) + return Token("EOF", "EOF", + SourcePos(i, self.lineno, self.columnno)) else: raise StopIteration - return (self.automaton.names[self.last_matched_state], - self.text[start:], start, lineno, columnno) - raise deterministic.LexerError(self.text, self.state, i - 1, - self.lineno, self.columnno) + return Token(self.automaton.names[self.last_matched_state], + self.text[start:], + SourcePos(start, lineno, columnno)) + source_pos = SourcePos(i - 1, self.lineno, self.columnno) + raise deterministic.LexerError(self.text, self.state, source_pos) def adjust_position(self, token): lineno = self.lineno Modified: pypy/dist/pypy/rlib/parsing/parsing.py ============================================================================== --- pypy/dist/pypy/rlib/parsing/parsing.py (original) +++ pypy/dist/pypy/rlib/parsing/parsing.py Wed Dec 20 12:15:45 2006 @@ -1,4 +1,5 @@ import py +from pypy.rlib.parsing.lexer import SourcePos from pypy.rlib.parsing.tree import Node, Symbol, Nonterminal class Rule(object): @@ -132,7 +133,7 @@ try: input = self.input[i] if self.terminal_equality(symbol, input): - result = (Symbol(symbol, input[1], input), i + 1, error) + result = (Symbol(symbol, input.source, input), i + 1, error) self.matched[i, symbol] = result return result else: @@ -149,20 +150,9 @@ return None, 0, error def terminal_equality(self, symbol, input): - return symbol == input[0] + return symbol == input.name -class SourcePos(object): - def __init__(self, i, lineno, columnno): - self.i = i - self.lineno = lineno - self.columnno = columnno - - def from_token(token): - _, _, i, lineno, columnno = token - return SourcePos(i, lineno, columnno) - from_token = staticmethod(from_token) - class PackratParser(object): def __init__(self, rules, startsymbol, parsetablefactory=LazyParseTable, check_for_left_recursion=True): @@ -190,7 +180,7 @@ result = table.match_symbol(0, self.startsymbol) if result[0] is None: error = result[2] - raise ParseError(SourcePos.from_token(input[error.pos]), error) + raise ParseError(input[error.pos].source_pos, error) return result[0] def has_left_recursion(self): @@ -273,7 +263,7 @@ try: input = self.input[i] if self.terminal_equality(%(symbol)r, input): - symbol = Symbol(%(symbol)r, input[1], input) + symbol = Symbol(%(symbol)r, input.name, input) result = (symbol, i + 1) self.matched_terminals%(number)s[i] = result return result Modified: pypy/dist/pypy/rlib/parsing/test/pygrammar.txt ============================================================================== --- pypy/dist/pypy/rlib/parsing/test/pygrammar.txt (original) +++ pypy/dist/pypy/rlib/parsing/test/pygrammar.txt Wed Dec 20 12:15:45 2006 @@ -61,8 +61,8 @@ import_what: "*" | "(" import_as_names ","? ")" | import_as_names; # the second NAME is the "as" (which is not a keyword in Python) -import_as_name: NAME (NAME NAME)?; -dotted_as_name: dotted_name (NAME NAME)?; +import_as_name: NAME ("as" NAME)?; +dotted_as_name: dotted_name ("as" NAME)?; import_as_names: import_as_name ("," import_as_name)*; dotted_as_names: dotted_as_name ("," dotted_as_name)*; dotted_name: NAME ("." NAME)*; @@ -116,7 +116,10 @@ dictitem: test [":"] test; lambdef: ["lambda"] varargslist? [":"] test; -trailer: "(" ")" | "(" arglist ")" | "[" subscriptlist "]" | "." NAME; +trailer: | | ; +call: ["(" ")"] | ["("] arglist [")"]; +subscription: ["["] >subscriptlist< ["]"]; +attraccess: ["."] NAME; subscriptlist: subscript ("," subscript)* ","?; subscript: "." "." "." | test? ":" test? sliceop? | test; sliceop: ":" test?; Modified: pypy/dist/pypy/rlib/parsing/test/test_lexer.py ============================================================================== --- pypy/dist/pypy/rlib/parsing/test/test_lexer.py (original) +++ pypy/dist/pypy/rlib/parsing/test/test_lexer.py Wed Dec 20 12:15:45 2006 @@ -16,23 +16,23 @@ l = self.get_lexer(rexs, names) r = l.get_runner("if: else: while:") t = r.find_next_token() - assert t == ("IF", "if", 0, 0, 0) + assert t == Token("IF", "if", SourcePos(0, 0, 0)) t = r.find_next_token() - assert t == ("COLON", ":", 2, 0, 2) + assert t == Token("COLON", ":", SourcePos(2, 0, 2)) t = r.find_next_token() - assert t == ("WHITE", " ", 3, 0, 3) + assert t == Token("WHITE", " ", SourcePos(3, 0, 3)) t = r.find_next_token() - assert t == ("ELSE", "else", 4, 0, 4) + assert t == Token("ELSE", "else", SourcePos(4, 0, 4)) t = r.find_next_token() - assert t == ("COLON", ":", 8, 0, 8) + assert t == Token("COLON", ":", SourcePos(8, 0, 8)) t = r.find_next_token() - assert t == ("WHITE", " ", 9, 0, 9) + assert t == Token("WHITE", " ", SourcePos(9, 0, 9)) t = r.find_next_token() - assert t == ("WHILE", "while", 10, 0, 10) + assert t == Token("WHILE", "while", SourcePos(10, 0, 10)) t = r.find_next_token() - assert t == ("COLON", ":", 15, 0, 15) + assert t == Token("COLON", ":", SourcePos(15, 0, 15)) py.test.raises(StopIteration, r.find_next_token) - assert [t[0] for t in l.tokenize("if if if: else while")] == "IF WHITE IF WHITE IF COLON WHITE ELSE WHITE WHILE".split() + assert [t.name for t in l.tokenize("if if if: else while")] == "IF WHITE IF WHITE IF COLON WHITE ELSE WHITE WHILE".split() def test_pro(self): digits = RangeExpression("0", "9") @@ -45,7 +45,7 @@ integers = StringExpression("0") | (RangeExpression("1", "9") + digits.kleene()) white = StringExpression(" ") l = self.get_lexer([keywords, atoms, vars, integers, white], ["KEYWORD", "ATOM", "VAR", "INT", "WHITE"]) - assert ([t[0] for t in l.tokenize("if A a 12341 0 else")] == + assert ([t.name for t in l.tokenize("if A a 12341 0 else")] == "KEYWORD WHITE VAR WHITE ATOM WHITE INT WHITE INT WHITE KEYWORD".split()) def test_ignore(self): @@ -54,7 +54,7 @@ StringExpression(" ")] names = ["IF", "ELSE", "WHILE", "COLON", "WHITE"] l = self.get_lexer(rexs, names, ["WHITE"]) - assert [t[0] for t in l.tokenize("if if if: else while")] == "IF IF IF COLON ELSE WHILE".split() + assert [t.name for t in l.tokenize("if if if: else while")] == "IF IF IF COLON ELSE WHILE".split() def test_errors(self): rexs = [StringExpression("if"), StringExpression("else"), @@ -66,7 +66,7 @@ print dir(info) print info.__class__ exc = info.value - assert exc.input[exc.index] == "a" + assert exc.input[exc.source_pos.i] == "a" def test_eof(self): rexs = [StringExpression("if"), StringExpression("else"), @@ -77,10 +77,10 @@ s = "if if if: else while" tokens = list(l.get_runner(s, eof=True)) print tokens - assert tokens[-1] == ("EOF", "EOF", len(s), 0, len(s)) + assert tokens[-1] == Token("EOF", "EOF", SourcePos(len(s), 0, len(s))) tokens = l.tokenize(s, eof=True) print tokens - assert tokens[-1] == ("EOF", "EOF", len(s), 0, len(s)) + assert tokens[-1] == Token("EOF", "EOF", SourcePos(len(s), 0, len(s))) def test_position(self): rexs = [StringExpression("if"), StringExpression("else"), @@ -90,16 +90,16 @@ l = self.get_lexer(rexs, names, ["WHITE"]) s = "if\nif if:\nelse while\n" tokens = list(l.get_runner(s, eof=True)) - assert tokens[0] == ("IF", "if", 0, 0, 0) - assert tokens[1] == ("NL", "\n", 2, 0, 2) - assert tokens[2] == ("IF", "if", 3, 1, 0) - assert tokens[3] == ("IF", "if", 6, 1, 3) - assert tokens[4] == ("COLON", ":", 8, 1, 5) - assert tokens[5] == ("NL", "\n", 9, 1, 6) - assert tokens[6] == ("ELSE", "else", 10, 2, 0) - assert tokens[7] == ("WHILE", "while", 15, 2, 5) - assert tokens[8] == ("NL", "\n", 20, 2, 10) - assert tokens[9] == ("EOF", "EOF", 21, 3, 0) + assert tokens[0] == Token("IF", "if", SourcePos(0, 0, 0)) + assert tokens[1] == Token("NL", "\n", SourcePos(2, 0, 2)) + assert tokens[2] == Token("IF", "if", SourcePos(3, 1, 0)) + assert tokens[3] == Token("IF", "if", SourcePos(6, 1, 3)) + assert tokens[4] == Token("COLON", ":", SourcePos(8, 1, 5)) + assert tokens[5] == Token("NL", "\n", SourcePos(9, 1, 6)) + assert tokens[6] == Token("ELSE", "else", SourcePos(10, 2, 0)) + assert tokens[7] == Token("WHILE", "while", SourcePos(15, 2, 5)) + assert tokens[8] == Token("NL", "\n", SourcePos(20, 2, 10)) + assert tokens[9] == Token("EOF", "EOF", SourcePos(21, 3, 0)) def test_position_ignore(self): rexs = [StringExpression("if"), StringExpression("else"), @@ -109,11 +109,27 @@ l = self.get_lexer(rexs, names, ["WHITE", "NL"]) s = "if\nif if:\nelse while\n" tokens = list(l.get_runner(s, eof=True)) - assert tokens[0] == ("IF", "if", 0, 0, 0) - assert tokens[1] == ("IF", "if", 3, 1, 0) - assert tokens[2] == ("IF", "if", 6, 1, 3) - assert tokens[3] == ("COLON", ":", 8, 1, 5) - assert tokens[4] == ("ELSE", "else", 10, 2, 0) - assert tokens[5] == ("WHILE", "while", 15, 2, 5) - assert tokens[6] == ("EOF", "EOF", 21, 3, 0) + assert tokens[0] == Token("IF", "if", SourcePos(0, 0, 0)) + assert tokens[1] == Token("IF", "if", SourcePos(3, 1, 0)) + assert tokens[2] == Token("IF", "if", SourcePos(6, 1, 3)) + assert tokens[3] == Token("COLON", ":", SourcePos(8, 1, 5)) + assert tokens[4] == Token("ELSE", "else", SourcePos(10, 2, 0)) + assert tokens[5] == Token("WHILE", "while", SourcePos(15, 2, 5)) + assert tokens[6] == Token("EOF", "EOF", SourcePos(21, 3, 0)) + def test_left_stuff_at_eof(self): + rexs = [StringExpression("if"), StringExpression("else"), + StringExpression("while"), StringExpression(":"), + StringExpression(" "), StringExpression("\n")] + names = ["IF", "ELSE", "WHILE", "COLON", "WHITE", "NL"] + l = self.get_lexer(rexs, names) + s = "if: whi" + runner = l.get_runner(s, eof=True) + tokens = [] + tok = runner.find_next_token() + assert tok.name == "IF" + tok = runner.find_next_token() + assert tok.name == "COLON" + tok = runner.find_next_token() + assert tok.name == "WHITE" + py.test.raises(deterministic.LexerError, runner.find_next_token) Modified: pypy/dist/pypy/rlib/parsing/test/test_parse.py ============================================================================== --- pypy/dist/pypy/rlib/parsing/test/test_parse.py (original) +++ pypy/dist/pypy/rlib/parsing/test/test_parse.py Wed Dec 20 12:15:45 2006 @@ -1,3 +1,4 @@ +from pypy.rlib.parsing.lexer import Token, SourcePos from pypy.rlib.parsing.parsing import * class EvaluateVisitor(object): @@ -46,13 +47,13 @@ r3 = Rule("primary", [["(", "additive", ")"], ["decimal"]]) r4 = Rule("decimal", [[symb] for symb in "0123456789"]) p = PackratParser([r1, r2, r3, r4], "additive") - print p.parse([(c, c, i, 0, i) for i, c in enumerate("2*(3+4)")]) - tree = p.parse([(c, c, i, 0, i) for i, c in enumerate("2*2*2*(7*3+4+5*6)")]) + print p.parse([Token(c, c, SourcePos(i, 0, i)) for i, c in enumerate("2*(3+4)")]) + tree = p.parse([Token(c, c, SourcePos(i, 0, i)) for i, c in enumerate("2*2*2*(7*3+4+5*6)")]) ast = tree.visit(ToAstVisistor()) - tree = p.parse([(c, c, i, 0, i) for i, c in enumerate("2*(3+4)")]) + tree = p.parse([Token(c, c, SourcePos(i, 0, i)) for i, c in enumerate("2*(3+4)")]) r = tree.visit(EvaluateVisitor()) assert r == 14 - tree = p.parse([(c, c, i, 0, i) for i, c in enumerate("2*(3+5*2*(2+6))")]) + tree = p.parse([Token(c, c, SourcePos(i, 0, i)) for i, c in enumerate("2*(3+5*2*(2+6))")]) print tree r = tree.visit(EvaluateVisitor()) assert r == 166 @@ -60,7 +61,7 @@ def test_bad(): r1 = Rule("S", [["x", "S", "x"], ["x"]]) p = PackratParser([r1], "S") - assert p.parse([(c, c, i, 0, i) for i, c in enumerate("xxxxxxxxxxxxxxx")]) is not None + assert p.parse([Token(c, c, SourcePos(i, 0, i)) for i, c in enumerate("xxxxxxxxxxxxxxx")]) is not None def test_leftrecursion_detection(): r1 = Rule("A", [["A"]]) @@ -72,6 +73,9 @@ def test_epsilon(): r1 = Rule("S", [["x", "S", "x"], ["y"], []]) p = PackratParser([r1], "S") - assert p.parse([(c, i) for i, c, in enumerate("xyx")]) is not None - assert p.parse([(c, i) for i, c, in enumerate("xx")]) is not None - t = p.parse([(c, i) for i, c, in enumerate("xxxxxx")]) + assert p.parse([Token(c, i, SourcePos(i, 0, i)) + for i, c, in enumerate("xyx")]) is not None + assert p.parse([Token(c, i, SourcePos(i, 0, i)) + for i, c, in enumerate("xx")]) is not None + t = p.parse([Token(c, i, SourcePos(i, 0, i)) + for i, c, in enumerate("xxxxxx")]) Modified: pypy/dist/pypy/rlib/parsing/test/test_pythonparse.py ============================================================================== --- pypy/dist/pypy/rlib/parsing/test/test_pythonparse.py (original) +++ pypy/dist/pypy/rlib/parsing/test/test_pythonparse.py Wed Dec 20 12:15:45 2006 @@ -1,7 +1,7 @@ """ test file to experiment with a an adapted CPython grammar """ import py -from pypy.rlib.parsing.lexer import Lexer +from pypy.rlib.parsing.lexer import Lexer, SourcePos, Token from pypy.rlib.parsing.deterministic import LexerError from pypy.rlib.parsing.tree import Nonterminal, Symbol, RPythonVisitor from pypy.rlib.parsing.parsing import PackratParser, Symbol, ParseError, Rule @@ -103,12 +103,11 @@ try: tokens = self.lexer.tokenize(s, eof=False) if len(tokens) == 1: - typ, s, _, _, _ = tokens[0] - yield typ, s, pos, row, col + yield tokens[0] continue except LexerError: pass - yield (typ, s, pos, row, col) + yield Token(typ, s, SourcePos(pos, row, col)) def test_simple(self): @@ -208,6 +207,13 @@ f() ** 2 f(x) * 2 f(x, y, z, *args) + 2 +f(x, y, abc=34, *arg, **kwargs) +""") + t = self.ToAST.transform(t) + + def test_trailers(self): + t = self.parse(""" +(a + b).foo[1 + i - j:](32, *args) """) t = self.ToAST.transform(t) Modified: pypy/dist/pypy/rlib/parsing/test/test_translate.py ============================================================================== --- pypy/dist/pypy/rlib/parsing/test/test_translate.py (original) +++ pypy/dist/pypy/rlib/parsing/test/test_translate.py Wed Dec 20 12:15:45 2006 @@ -27,7 +27,7 @@ tokens = l2.tokenize(s) else: tokens = l1.tokenize(s) - return "-%-".join([t[0] for t in tokens]) + return "-%-".join([t.name for t in tokens]) res = lex("if A a 12341 0 else").split("-%-") assert res == ("KEYWORD WHITE VAR WHITE ATOM WHITE INT WHITE " "INT WHITE KEYWORD").split() @@ -50,8 +50,10 @@ r3 = Rule("primary", [["(", "additive", ")"], ["decimal"]]) r4 = Rule("decimal", [[symb] for symb in "0123456789"]) p = PackratParser([r0, r1, r2, r3, r4], "expression") - tree = p.parse([(c, i) for i, c in enumerate(list("2*(3+4)") + ["EOF"])]) - data = [(c, i) for i, c in enumerate(list("2*(3+4)") + ["EOF"])] + tree = p.parse([Token(c, i, SourcePos(i, 0, i)) + for i, c in enumerate(list("2*(3+4)") + ["EOF"])]) + data = [Token(c, i, SourcePos(i, 0, i)) + for i, c in enumerate(list("2*(3+4)") + ["EOF"])] print tree def parse(choose): tree = p.parse(data, lazy=False) @@ -76,8 +78,10 @@ compiler = ParserCompiler(p) kls = compiler.compile() p = kls() - tree = p.parse([(c, i) for i, c in enumerate(list("2*(3+4)") + ["EOF"])]) - data = [(c, i) for i, c in enumerate(list("2*(3+4)") + ["EOF"])] + tree = p.parse([Token(c, i, SourcePos(i, 0, i)) + for i, c in enumerate(list("2*(3+4)") + ["EOF"])]) + data = [Token(c, i, SourcePos(i, 0, i)) + for i, c in enumerate(list("2*(3+4)") + ["EOF"])] print tree p = kls() def parse(choose): From mwh at codespeak.net Wed Dec 20 12:35:52 2006 From: mwh at codespeak.net (mwh at codespeak.net) Date: Wed, 20 Dec 2006 12:35:52 +0100 (CET) Subject: [pypy-svn] r35914 - pypy/dist/pypy/translator/goal Message-ID: <20061220113552.0442E10082@code0.codespeak.net> Author: mwh Date: Wed Dec 20 12:35:50 2006 New Revision: 35914 Modified: pypy/dist/pypy/translator/goal/bench-cronjob.py Log: didn't mean to make a _stackless_ call-likely-builtin build Modified: pypy/dist/pypy/translator/goal/bench-cronjob.py ============================================================================== --- pypy/dist/pypy/translator/goal/bench-cronjob.py (original) +++ pypy/dist/pypy/translator/goal/bench-cronjob.py Wed Dec 20 12:35:50 2006 @@ -171,9 +171,10 @@ c--gc=framework c--thread--_objspace-std-withstrdict--profopt='-c "from richards import *;main(iterations=1)"' c--stackless - c--stackless--profopt='-c "from richards import *;main(iterations=1)"'--_objspace-opcodes-CALL_LIKELY_BUILTIN + c--stackless--profopt='-c "from richards import *;main(iterations=1)"' c--stackless--_objspace-std-withstrdict--profopt='-c "from richards import *;main(iterations=1)"' c--profopt='-c "from richards import *;main(iterations=1)"' + c--profopt='-c "from richards import *;main(iterations=1)"'--_objspace-opcodes-CALL_LIKELY_BUILTIN c--_objspace-std-withstrdict--profopt='-c "from richards import *;main(iterations=1)"' c--gc=framework--_objspace-std-withstrdict--profopt='-c "from richards import *;main(iterations=1)"' cli From mwh at codespeak.net Wed Dec 20 13:00:38 2006 From: mwh at codespeak.net (mwh at codespeak.net) Date: Wed, 20 Dec 2006 13:00:38 +0100 (CET) Subject: [pypy-svn] r35915 - in pypy/dist/pypy/translator: benchmark goal Message-ID: <20061220120038.2CC1F10086@code0.codespeak.net> Author: mwh Date: Wed Dec 20 13:00:33 2006 New Revision: 35915 Added: pypy/dist/pypy/translator/benchmark/ pypy/dist/pypy/translator/benchmark/__init__.py (contents, props changed) pypy/dist/pypy/translator/benchmark/autopath.py - copied unchanged from r35910, pypy/dist/pypy/tool/autopath.py pypy/dist/pypy/translator/benchmark/bench-custom.py - copied unchanged from r35910, pypy/dist/pypy/translator/goal/bench-custom.py Removed: pypy/dist/pypy/translator/goal/bench-custom.py Log: make a translator.benchmark package, hopefully to contain some more principled ways of creating and viewing benchmark data. Added: pypy/dist/pypy/translator/benchmark/__init__.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/translator/benchmark/__init__.py Wed Dec 20 13:00:33 2006 @@ -0,0 +1 @@ +# From mwh at codespeak.net Wed Dec 20 13:39:01 2006 From: mwh at codespeak.net (mwh at codespeak.net) Date: Wed, 20 Dec 2006 13:39:01 +0100 (CET) Subject: [pypy-svn] r35916 - in pypy/dist/pypy/translator/benchmark: . test Message-ID: <20061220123901.899B41007D@code0.codespeak.net> Author: mwh Date: Wed Dec 20 13:38:56 2006 New Revision: 35916 Added: pypy/dist/pypy/translator/benchmark/result.py (contents, props changed) pypy/dist/pypy/translator/benchmark/test/ pypy/dist/pypy/translator/benchmark/test/__init__.py (contents, props changed) pypy/dist/pypy/translator/benchmark/test/test_result.py (contents, props changed) Modified: pypy/dist/pypy/translator/benchmark/bench-custom.py Log: move the BenchmarkResult class into its own file (so it's not always pickled as __main__.BenchmarkResult...) and add a simple test. Modified: pypy/dist/pypy/translator/benchmark/bench-custom.py ============================================================================== --- pypy/dist/pypy/translator/benchmark/bench-custom.py (original) +++ pypy/dist/pypy/translator/benchmark/bench-custom.py Wed Dec 20 13:38:56 2006 @@ -1,7 +1,7 @@ # benchmarks on a unix machine. -# to be executed in the goal folder, -# where a couple of pypy-* files is expected. +import autopath +from pypy.translator.benchmark.result import BenchmarkResult import os, sys, time, pickle, re PYSTONE_CMD = 'from test import pystone;pystone.main(%s)' @@ -12,55 +12,12 @@ RICHARDS_PATTERN = 'Average time per iteration:' RICHARDS_ASCENDING_GOOD = False -class BenchmarkResult(object): - - def __init__(self, filename, max_results=10): - self.filename = filename - self.max_results = max_results - if os.path.exists(filename): - f = open(filename, 'r') - self.n_results = pickle.load(f) - self.best_result = pickle.load(f) - f.close() - # any exception while loading the file is best reported - # as a crash, instead of as a silent loss of all the - # data :-/ - else: - self.n_results = {} - self.best_result = {} - - def is_stable(self, name): - try: - return self.n_results[name] >= self.max_results - except: - return False - - def update(self, name, result, ascending_good): - try: - if ascending_good: - self.best_result[name] = max(self.best_result[name], result) - else: - self.best_result[name] = min(self.best_result[name], result) - except KeyError: - self.n_results[name] = 0 - self.best_result[name] = result - self.n_results[name] += 1 - - f = open(self.filename, 'w') - pickle.dump(self.n_results , f) - pickle.dump(self.best_result, f) - f.close() - - def get_best_result(self, name): - return self.best_result[name] - - def get_result(txt, pattern): for line in txt.split('\n'): if line.startswith(pattern): break else: - print 'warning: this is no valid output' + print 'warning: this is not valid output' return 99999.0 return float(line.split()[len(pattern.split())]) Added: pypy/dist/pypy/translator/benchmark/result.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/translator/benchmark/result.py Wed Dec 20 13:38:56 2006 @@ -0,0 +1,44 @@ +import os, pickle + +class BenchmarkResult(object): + + def __init__(self, filename, max_results=10): + self.filename = filename + self.max_results = max_results + if os.path.exists(filename): + f = open(filename, 'r') + self.n_results = pickle.load(f) + self.best_result = pickle.load(f) + f.close() + # any exception while loading the file is best reported + # as a crash, instead of as a silent loss of all the + # data :-/ + else: + self.n_results = {} + self.best_result = {} + + def is_stable(self, name): + try: + return self.n_results[name] >= self.max_results + except: + return False + + def update(self, name, result, ascending_good): + try: + if ascending_good: + self.best_result[name] = max(self.best_result[name], result) + else: + self.best_result[name] = min(self.best_result[name], result) + except KeyError: + self.n_results[name] = 0 + self.best_result[name] = result + self.n_results[name] += 1 + + f = open(self.filename, 'w') + pickle.dump(self.n_results , f) + pickle.dump(self.best_result, f) + f.close() + + def get_best_result(self, name): + return self.best_result[name] + Added: pypy/dist/pypy/translator/benchmark/test/__init__.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/translator/benchmark/test/__init__.py Wed Dec 20 13:38:56 2006 @@ -0,0 +1 @@ +# Added: pypy/dist/pypy/translator/benchmark/test/test_result.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/translator/benchmark/test/test_result.py Wed Dec 20 13:38:56 2006 @@ -0,0 +1,19 @@ +import py +from pypy.translator.benchmark import result + +temp = py.test.ensuretemp("report") + +def test_simple(): + fname = temp.join("simple") + b = result.BenchmarkResult(str(fname), 3) + + b.update('foo', 1, True) + assert b.get_best_result('foo') == 1 + + b.update('foo', 2, True) + assert b.get_best_result('foo') == 2 + assert not b.is_stable('foo') + + b.update('foo', 1, True) + assert b.get_best_result('foo') == 2 + assert b.is_stable('foo') From ericvrp at codespeak.net Wed Dec 20 14:20:12 2006 From: ericvrp at codespeak.net (ericvrp at codespeak.net) Date: Wed, 20 Dec 2006 14:20:12 +0100 (CET) Subject: [pypy-svn] r35917 - in pypy/dist/pypy/jit/codegen/llvm: . test Message-ID: <20061220132012.0E08E1007E@code0.codespeak.net> Author: ericvrp Date: Wed Dec 20 14:20:10 2006 New Revision: 35917 Modified: pypy/dist/pypy/jit/codegen/llvm/rgenop.py pypy/dist/pypy/jit/codegen/llvm/test/test_genc_ts.py Log: jit/codegen/llvm - temporary workaround/hack issue with getelementptr on constants - restructure the tests currently being worked on - add some operations releated to pointer handling Modified: pypy/dist/pypy/jit/codegen/llvm/rgenop.py ============================================================================== --- pypy/dist/pypy/jit/codegen/llvm/rgenop.py (original) +++ pypy/dist/pypy/jit/codegen/llvm/rgenop.py Wed Dec 20 14:20:10 2006 @@ -380,8 +380,8 @@ op_char_lt = op_uint_lt = op_float_lt = op_int_lt op_char_le = op_uint_le = op_float_le = op_int_le - op_char_eq = op_uint_eq = op_float_eq = op_unichar_eq = op_int_eq - op_char_ne = op_uint_ne = op_float_ne = op_unichar_ne = op_int_ne + op_char_eq = op_uint_eq = op_float_eq = op_unichar_eq = op_ptr_eq = op_int_eq + op_char_ne = op_uint_ne = op_float_ne = op_unichar_ne = op_ptr_ne = op_int_ne op_char_gt = op_uint_gt = op_float_gt = op_int_gt op_char_ge = op_uint_ge = op_float_ge = op_int_ge @@ -538,6 +538,13 @@ gv_condition.operand(), targetbuilder.nextlabel, self.nextlabel)) return targetbuilder + def _is_false(self, gv_x, nullstr='0'): + log('%s Builder._is_false %s' % (self.block.label, gv_x.operand())) + gv_result = Var('bool') + self.asm.append(' %s=seteq %s,%s' % ( + gv_result.operand2(), gv_x.operand(), nullstr)) + return gv_result + def _is_true(self, gv_x, nullstr='0'): log('%s Builder._is_true %s' % (self.block.label, gv_x.operand())) gv_result = Var('bool') @@ -546,7 +553,9 @@ return gv_result op_bool_is_true = op_char_is_true = op_unichar_is_true = op_int_is_true =\ - op_uint_is_true = _is_true + op_uint_is_true = op_ptr_nonzero = _is_true + + op_ptr_iszero = _is_false def op_float_is_true(self, gv_x): return self._is_true(gv_x, '0.0') @@ -561,9 +570,10 @@ else: assert fieldsize == 2 t = 'short' + gv_ptr_var = self._as_var(gv_ptr) gv_p = Var(t + '*') self.asm.append(' %s=getelementptr %s,int %s' % ( - gv_p.operand2(), gv_ptr.operand(), offset / fieldsize)) + gv_p.operand2(), gv_ptr_var.operand(), offset / fieldsize)) gv_result = Var(t) self.asm.append(' %s=load %s' % ( gv_result.operand2(), gv_p.operand())) @@ -580,17 +590,27 @@ # else: # assert fieldsize == 2 # gv_result = Var('short') + gv_ptr_var = self._as_var(gv_ptr) gv_p = Var(gv_value.type+'*') self.asm.append(' %s=getelementptr %s,int %s' % ( - gv_p.operand2(), gv_ptr.operand(), offset / fieldsize)) + gv_p.operand2(), gv_ptr_var.operand(), offset / fieldsize)) self.asm.append(' store %s,%s' % ( gv_value.operand2(), gv_p.operand())) + def XXXgenop_getsubstruct(self, (offset, fieldsize), gv_ptr): + log('%s Builder.genop_getsubstruct [%d]%d,%s' % ( + self.block.label, offset, fieldsize, gv_ptr.operand())) + gv_ptr_var = self._as_var(gv_ptr) + gv_sub = Var(gv_ptr.type) + self.asm.append(' %s=getelementptr %s,%d' % ( + gv_sub.operand2(), gv_ptr_var.operand(), offset)) + return gv_sub + def genop_getarrayitem(self, arraytoken, gv_ptr, gv_index): array_length_offset, array_items_offset, itemsize = arraytoken log('%s Builder.genop_getarrayitem %s,%s,%s' % ( self.block.label, arraytoken, gv_ptr.operand(), gv_index.operand())) - + gv_i = Var(gv_index.type) try: offset = array_items_offset / itemsize @@ -599,10 +619,12 @@ self.asm.append(' %s=add %s,%d' % ( gv_i.operand2(), gv_index.operand(), offset)) #/itemsize correct? - gv_p = Var(gv_ptr.type) + gv_ptr_var = self._as_var(gv_ptr) + gv_p = Var(gv_ptr_var.type) self.asm.append(' %s=getelementptr %s,%s' % ( - gv_p.operand2(), gv_ptr.operand(), gv_i.operand())) - gv_result = Var(gv_ptr.type[:-1]) + gv_p.operand2(), gv_ptr_var.operand(), gv_i.operand())) + + gv_result = Var(gv_ptr_var.type[:-1]) self.asm.append(' %s=load %s' % ( gv_result.operand2(), gv_p.operand())) return gv_result @@ -638,6 +660,15 @@ gv_result.operand2(), self.block.label, arraytoken, gv_ptr)) return gv_result + def _as_var(self, gv): + if gv.is_const: + gv_var = Var(gv.type) + #XXX provide correct cast here + self.asm.append(' %s=inttoptr int %s to %s' % ( + gv_var.operand2(), gv.operand2(), gv_var.type)) + return gv_var + return gv + def genop_setarrayitem(self, arraytoken, gv_ptr, gv_index, gv_value): array_length_offset, array_items_offset, itemsize = arraytoken log('%s Builder.genop_setarrayitem %s,%s,%s,%s' % ( @@ -651,9 +682,10 @@ self.asm.append(' %s=add %s,%d' % ( gv_i.operand2(), gv_index.operand(), offset)) #/itemsize correct? - gv_p = Var(gv_ptr.type) + gv_ptr_var = self._as_var(gv_ptr) + gv_p = Var(gv_ptr_var.type) self.asm.append(' %s=getelementptr %s,%s' % ( - gv_p.operand2(), gv_ptr.operand(), gv_i.operand())) + gv_p.operand2(), gv_ptr_var.operand(), gv_i.operand())) self.asm.append(' store %s,%s' % ( gv_value.operand(), gv_p.operand())) 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 Wed Dec 20 14:20:10 2006 @@ -4,6 +4,10 @@ from pypy.jit.codegen.llvm.rgenop import RLLVMGenOp +skip_passing = False +skip_failing = True + + class LLVMTimeshiftingTestMixin(I386TimeshiftingTestMixin): RGenOp = RLLVMGenOp @@ -17,57 +21,58 @@ def skip(self): py.test.skip("WIP") - #passing... - #test_very_simple = skip - #test_convert_const_to_redbox = skip - #test_simple_opt_const_propagation2 = skip - #test_simple_opt_const_propagation1 = skip - #test_loop_folding = skip - #test_loop_merging = skip - #test_two_loops_merging = skip - #test_convert_greenvar_to_redvar = skip - #test_green_across_split = skip - #test_merge_const_before_return = skip - #test_merge_3_redconsts_before_return = skip - #test_arith_plus_minus = skip - #test_plus_minus_all_inlined = skip - #test_call_simple = skip - #test_call_2 = skip - #test_call_3 = skip - #test_call_4 = skip - #test_void_call = skip - #test_green_call = skip - #test_split_on_green_return = skip - #test_recursive_call = skip - #test_simple_indirect_call = skip - #test_normalize_indirect_call = skip - #test_normalize_indirect_call_more = skip - #test_green_red_mismatch_in_call = skip - #test_red_call_ignored_result = skip - #test_simple_struct = skip - #test_simple_array = skip + if skip_passing: + test_very_simple = skip + test_convert_const_to_redbox = skip + test_simple_opt_const_propagation2 = skip + test_simple_opt_const_propagation1 = skip + test_loop_folding = skip + test_loop_merging = skip + test_two_loops_merging = skip + test_convert_greenvar_to_redvar = skip + test_green_across_split = skip + test_merge_const_before_return = skip + test_merge_3_redconsts_before_return = skip + test_arith_plus_minus = skip + test_plus_minus_all_inlined = skip + test_call_simple = skip + test_call_2 = skip + test_call_3 = skip + test_call_4 = skip + test_void_call = skip + test_green_call = skip + test_split_on_green_return = skip + test_recursive_call = skip + test_simple_indirect_call = skip + test_normalize_indirect_call = skip + test_normalize_indirect_call_more = skip + test_green_red_mismatch_in_call = skip + test_red_call_ignored_result = skip + test_simple_struct = skip + test_simple_array = skip + test_setarrayitem = skip #failing... - test_degenerated_before_return = skip - test_degenerated_before_return_2 = skip - test_degenerated_at_return = skip - test_degenerated_via_substructure = skip - test_degenerate_with_voids = skip - test_red_virtual_container = skip - test_setarrayitem = skip - test_red_array = skip - test_red_struct_array = skip - test_red_varsized_struct = skip - test_array_of_voids = skip - test_red_propagate = skip - test_red_subcontainer = skip - test_red_subcontainer_cast = skip - test_merge_structures = skip - test_green_with_side_effects = skip - test_recursive_with_red_termination_condition = skip - test_simple_meth = skip - test_simple_red_meth = skip - test_compile_time_const_tuple = skip - test_residual_red_call = skip - test_residual_red_call_with_exc = skip + if skip_failing: + test_degenerated_before_return = skip + test_degenerated_before_return_2 = skip + test_degenerated_at_return = skip + test_degenerated_via_substructure = skip + test_degenerate_with_voids = skip + test_red_virtual_container = skip + test_red_array = skip + test_red_struct_array = skip + test_red_varsized_struct = skip + test_array_of_voids = skip + test_red_propagate = skip + test_red_subcontainer = skip + test_red_subcontainer_cast = skip + test_merge_structures = skip + test_green_with_side_effects = skip + test_recursive_with_red_termination_condition = skip + test_simple_meth = skip + test_simple_red_meth = skip + test_compile_time_const_tuple = skip + test_residual_red_call = skip + test_residual_red_call_with_exc = skip From mwh at codespeak.net Wed Dec 20 14:22:26 2006 From: mwh at codespeak.net (mwh at codespeak.net) Date: Wed, 20 Dec 2006 14:22:26 +0100 (CET) Subject: [pypy-svn] r35918 - pypy/dist/pypy/config Message-ID: <20061220132226.ED5D21007E@code0.codespeak.net> Author: mwh Date: Wed Dec 20 14:22:23 2006 New Revision: 35918 Modified: pypy/dist/pypy/config/pypyoption.py Log: add a --faassen command line optimization that enables all optimizations. Modified: pypy/dist/pypy/config/pypyoption.py ============================================================================== --- pypy/dist/pypy/config/pypyoption.py (original) +++ pypy/dist/pypy/config/pypyoption.py Wed Dec 20 14:22:23 2006 @@ -121,6 +121,19 @@ BoolOption("oldstyle", "specify whether the default metaclass should be classobj", default=False, cmdline="--oldstyle"), + + BoolOption("allopts", + "enable all optimizations", + default=False, + requires=[("objspace.opcodes.CALL_LIKELY_BUILTIN", True), + ("translation.withsmallfuncsets", 5), + ("translation.profopt", + "-c 'from richards import main;main(); from test import pystone; pystone.main()'"), + ("objspace.std.withstrjoin", True), + ("objspace.std.withstrslice", True), + ("objspace.std.withsmallint", True), + ], + cmdline="--faassen") ]), BoolOption("lowmem", "Try to use little memory during translation", default=False, cmdline="--lowmem", From mwh at codespeak.net Wed Dec 20 14:24:25 2006 From: mwh at codespeak.net (mwh at codespeak.net) Date: Wed, 20 Dec 2006 14:24:25 +0100 (CET) Subject: [pypy-svn] r35919 - pypy/dist/pypy/config Message-ID: <20061220132425.DD5D11007E@code0.codespeak.net> Author: mwh Date: Wed Dec 20 14:24:25 2006 New Revision: 35919 Modified: pypy/dist/pypy/config/pypyoption.py Log: forgot one Modified: pypy/dist/pypy/config/pypyoption.py ============================================================================== --- pypy/dist/pypy/config/pypyoption.py (original) +++ pypy/dist/pypy/config/pypyoption.py Wed Dec 20 14:24:25 2006 @@ -132,6 +132,7 @@ ("objspace.std.withstrjoin", True), ("objspace.std.withstrslice", True), ("objspace.std.withsmallint", True), + ("objspace.std.withrangelist", True), ], cmdline="--faassen") ]), From santagada at codespeak.net Wed Dec 20 15:19:21 2006 From: santagada at codespeak.net (santagada at codespeak.net) Date: Wed, 20 Dec 2006 15:19:21 +0100 (CET) Subject: [pypy-svn] r35920 - in pypy/dist/pypy/lang/js: . test Message-ID: <20061220141921.6E75F1008B@code0.codespeak.net> Author: santagada Date: Wed Dec 20 15:19:05 2006 New Revision: 35920 Modified: pypy/dist/pypy/lang/js/astgen.py pypy/dist/pypy/lang/js/interpreter.py pypy/dist/pypy/lang/js/jsobj.py pypy/dist/pypy/lang/js/reference.py pypy/dist/pypy/lang/js/test/test_interp.py Log: only 3 tests failling now. Modified: pypy/dist/pypy/lang/js/astgen.py ============================================================================== --- pypy/dist/pypy/lang/js/astgen.py (original) +++ pypy/dist/pypy/lang/js/astgen.py Wed Dec 20 15:19:05 2006 @@ -60,6 +60,8 @@ def __init__(self, name, initialiser=None): self.name = name self.initialiser = initialiser + def __str__(self): + return ""%(str(self.name), str(self.initialiser)) class If(Node): def __init__(self, condition, thenPart=None, elsePart=None): @@ -96,6 +98,9 @@ def __init__(self, name, value): self.name = name self.value = value + + def __repr__(self): + return "<%s : %s>"%(str(self.name), str(self.value)) class Return(Node): def __init__(self, expr): Modified: pypy/dist/pypy/lang/js/interpreter.py ============================================================================== --- pypy/dist/pypy/lang/js/interpreter.py (original) +++ pypy/dist/pypy/lang/js/interpreter.py Wed Dec 20 15:19:05 2006 @@ -34,7 +34,7 @@ def run(self): """run the interpreter""" - self.script.call(self.global_context) + return self.script.call(self.global_context) @@ -67,6 +67,7 @@ writer(",".join([i.GetValue().ToString() for i in self.arglist.call(ctx)])) else: w_obj = ctx.resolve_identifier(name).GetValue() + print "arglist = ", self.arglist retval = w_obj.Call(ctx=ctx, args=[i for i in self.arglist.call(ctx)]) return retval @@ -176,6 +177,7 @@ class __extend__(List): def call(self, ctx): + print "nodes = ", self.nodes return [node.call(ctx) for node in self.nodes] class __extend__(New): @@ -194,14 +196,15 @@ return W_Number(self.num) def get_literal(self): - # XXX Think about a shortcut later - return str(W_Number(self.num)) + return W_Number(self.num).ToString() class __extend__(ObjectInit): def call(self, ctx): w_obj = W_Object() + print "properties = ", self.properties for property in self.properties: name = property.name.get_literal() + print "prop name = ", name w_expr = property.value.call(ctx).GetValue() w_obj.Put(name, w_expr) return w_obj @@ -246,7 +249,7 @@ return W_String(self.strval) def get_literal(self): - return self.strval + return W_String(self.strval).ToString() class __extend__(Return): def call(self, ctx): @@ -263,10 +266,12 @@ tryresult = self.tryblock.call(ctx) except ThrowException, excpt: e = excpt - nctx = ExecutionContext(ctx) - nctx.assign(self.catchparam, e.exception) if self.catchblock is not None: - tryresult = self.catchblock.call(nctx) + obj = W_Object() + obj.Put(self.catchparam, e.exception) + ctx.push_object(obj) + tryresult = self.catchblock.call(ctx) + ctx.pop_object() if self.finallyblock is not None: tryresult = self.finallyblock.call(ctx) Modified: pypy/dist/pypy/lang/js/jsobj.py ============================================================================== --- pypy/dist/pypy/lang/js/jsobj.py (original) +++ pypy/dist/pypy/lang/js/jsobj.py Wed Dec 20 15:19:05 2006 @@ -41,6 +41,11 @@ def ToNumber(self): return NaN + def get_literal(self): + return self.ToString() + + __str__ = get_literal + def __repr__(self): return "<%s(%s)>" % (self.__class__.__name__, self.ToString()) @@ -64,6 +69,8 @@ return W_Object() def Get(self, P): + if not isinstance(P, str): + P = P.ToString() if P in self.propdict: return self.propdict[P].value if self.Prototype is None: return w_Undefined return self.Prototype.Get(P) # go down the prototype chain @@ -76,6 +83,8 @@ return self.Prototype.CanPut(P) def Put(self, P, V): + if not isinstance(P, str): + P = P.ToString() if not self.CanPut(P): return if P in self.propdict: self.propdict[P].value = V @@ -118,9 +127,16 @@ def ToString(self): return "[object %s]"%(self.Class,) + def __str__(self): + return ""%(self.Class, + self.propdict, self.Prototype) + class W_Arguments(W_Object): def __init__(self, callee, args): W_Object.__init__(self) + self.Class = "arguments" + self.propdict.pop("toString") + self.propdict.pop("prototype") self.Put('callee', callee) self.Put('length', len(args)) for i, arg in enumerate(args): @@ -130,6 +146,7 @@ """The object used on function calls to hold arguments and this""" def __init__(self): W_Object.__init__(self) + self.Class = "Activation" self.propdict.pop("toString") self.propdict.pop("prototype") @@ -143,20 +160,22 @@ self.scope = ctx.scope[:] def Call(self, ctx, args=[], this=None): - print args + print "* start of function call" + print " args = ", args act = ActivationObject() - for i, arg in enumerate(args): + for i, arg in enumerate(self.function.params): try: value = args[i] except IndexError: value = w_Undefined act.Put(self.function.params[i], value) act.Put('this', this) - print act.propdict + print " act.propdict = ", act.propdict w_Arguments = W_Arguments(self, args) act.Put('arguments', w_Arguments) newctx = function_context(self.scope, act, this) val = self.function.body.call(ctx=newctx) + print "* end of function call return = ", val return val class W_Undefined(W_Root): @@ -207,7 +226,7 @@ class W_Number(W_Primitive): def __init__(self, floatval): - print "novo numero" + print "w_number = ", floatval self.floatval = floatval def ToString(self): @@ -248,6 +267,9 @@ def ToBoolean(self): return bool(self.list_w) + + def __str__(self): + return str(self.list_w) w_Undefined = W_Undefined() w_Null = W_Null() Modified: pypy/dist/pypy/lang/js/reference.py ============================================================================== --- pypy/dist/pypy/lang/js/reference.py (original) +++ pypy/dist/pypy/lang/js/reference.py Wed Dec 20 15:19:05 2006 @@ -2,20 +2,26 @@ class Reference(object): """Reference Type""" - def __init__(self, propertyname, baseobject=None): - self.baseobject = baseobject - self.propertyname = propertyname + def __init__(self, property_name, base=None): + self.base = base + self.property_name = property_name def GetValue(self): - if self.baseobject is None: + if self.base is None: raise ReferenceError - return self.baseobject.Get(self.propertyname) + return self.base.Get(self.property_name) def PutValue(self, w, ctx): - base = self.baseobject - if self.baseobject is None: + base = self.base + if self.base is None: base = ctx.scope[-1] - base.Put(self.propertyname, w) + base.Put(self.property_name, w) + + def GetBase(self): + return self.base + + def GetPropertyName(self): + return self.property_name def __str__(self): - return str(self.baseobject) + " : " + str(self.propertyname) \ No newline at end of file + return "< " + str(self.base) + " -> " + str(self.property_name) + " >" \ No newline at end of file Modified: pypy/dist/pypy/lang/js/test/test_interp.py ============================================================================== --- pypy/dist/pypy/lang/js/test/test_interp.py (original) +++ pypy/dist/pypy/lang/js/test/test_interp.py Wed Dec 20 15:19:05 2006 @@ -41,7 +41,8 @@ assert l == assval def assert_result(self, code, result): - r = code.call(ExecutionContext()) + inter = interpreter.Interpreter(code) + r = inter.run() assert r.ToString() == result.ToString() def test_interp_parse(self): From santagada at codespeak.net Wed Dec 20 19:06:41 2006 From: santagada at codespeak.net (santagada at codespeak.net) Date: Wed, 20 Dec 2006 19:06:41 +0100 (CET) Subject: [pypy-svn] r35921 - in pypy/dist/pypy/lang/js: . test Message-ID: <20061220180641.DD8BA10093@code0.codespeak.net> Author: santagada Date: Wed Dec 20 19:06:32 2006 New Revision: 35921 Modified: pypy/dist/pypy/lang/js/interpreter.py pypy/dist/pypy/lang/js/jsobj.py pypy/dist/pypy/lang/js/test/test_interp.py Log: Finished the work on while loops and object literals just one test is failing Modified: pypy/dist/pypy/lang/js/interpreter.py ============================================================================== --- pypy/dist/pypy/lang/js/interpreter.py (original) +++ pypy/dist/pypy/lang/js/interpreter.py Wed Dec 20 19:06:32 2006 @@ -118,7 +118,9 @@ class __extend__(If): def call(self, ctx=None): - if self.condition.call(ctx).ToBoolean(): + temp = self.condition.call(ctx) + print "if condition = ", temp + if temp.ToBoolean(): return self.thenPart.call(ctx) else: return self.elsePart.call(ctx) @@ -135,6 +137,7 @@ # TODO complete the funcion with strings comparison s1 = x.ToPrimitive('Number') s2 = y.ToPrimitive('Number') + print "ARC x = %s, y = %s"%(str(s1),str(s2)) if not (isinstance(s1, W_String) and isinstance(s2, W_String)): s4 = s1.ToNumber() s5 = s2.ToNumber() @@ -162,6 +165,7 @@ s2 = self.left.call(ctx).GetValue() s4 = self.right.call(ctx).GetValue() s5 = ARC(s2, s4) + print "< ARC result = ", s5 if s5 is None: return W_Boolean(False) else: Modified: pypy/dist/pypy/lang/js/jsobj.py ============================================================================== --- pypy/dist/pypy/lang/js/jsobj.py (original) +++ pypy/dist/pypy/lang/js/jsobj.py Wed Dec 20 19:06:32 2006 @@ -210,6 +210,9 @@ return 1.0 return 0.0 + def ToBoolean(self): + return self.boolval + class W_String(W_Primitive): def __init__(self, strval): self.strval = strval @@ -237,7 +240,9 @@ return str(self.floatval) def ToBoolean(self): - return W_Boolean(bool(self.floatval)) + if self.floatval == 0.0 or self.floatval == NaN: + return False + return bool(self.floatval) def ToNumber(self): return self.floatval Modified: pypy/dist/pypy/lang/js/test/test_interp.py ============================================================================== --- pypy/dist/pypy/lang/js/test/test_interp.py (original) +++ pypy/dist/pypy/lang/js/test/test_interp.py Wed Dec 20 19:06:32 2006 @@ -233,9 +233,16 @@ print(o); """, ["[object Object]"]) + def test_function_name(self): + py.test.skip("not ready yet") + self.assert_prints(""" + function x() { + print("my name is x"); + } + x(); + """, ["my name is x"]) + def test_new_with_function(self): - - c= """ x = function() {this.info = 'hello';}; o = new x(); From stephan at codespeak.net Wed Dec 20 19:18:40 2006 From: stephan at codespeak.net (stephan at codespeak.net) Date: Wed, 20 Dec 2006 19:18:40 +0100 (CET) Subject: [pypy-svn] r35922 - in pypy/dist/pypy: lib lib/app_test lib/test2 module/_stackless/test Message-ID: <20061220181840.55E041009A@code0.codespeak.net> Author: stephan Date: Wed Dec 20 19:18:39 2006 New Revision: 35922 Added: pypy/dist/pypy/lib/app_test/test_stackless_pickling.py - copied, changed from r35891, pypy/dist/pypy/module/_stackless/test/test_stackless_pickling.py Removed: pypy/dist/pypy/lib/test2/test_stackless.py pypy/dist/pypy/module/_stackless/test/test_stackless.py pypy/dist/pypy/module/_stackless/test/test_stackless_pickling.py Modified: pypy/dist/pypy/lib/app_test/test_stackless.py pypy/dist/pypy/lib/stackless_new.py Log: fixed the stackless_new implementation such that it doesn't need to be reinitialized after every test. Included the test2/test_stackless.py tests in app_test/test_stackless (and skip them, because they are not yet working with stackless_new). Moved the module/_stackless/test/test_stackless_pickling.py tests over to app_test and modified to be pure application test suite (they pass with CStackless and pypy-c, not sure though, how to disable for py.py and CPython) Modified: pypy/dist/pypy/lib/app_test/test_stackless.py ============================================================================== --- pypy/dist/pypy/lib/app_test/test_stackless.py (original) +++ pypy/dist/pypy/lib/app_test/test_stackless.py Wed Dec 20 19:18:39 2006 @@ -11,15 +11,12 @@ if 'coroutine' in dir(stackless): stackless_c = False raise ImportError("We are running pypy-c") - withinit = False except ImportError: stackless_c = False try: from pypy.lib import stackless_new as stackless except ImportError, e: skip('cannot import stackless: %s' % (e,)) - #from pypy.lib import stackless - withinit = True def pypy_skip(txt): "don't skip, if we are running with CStackless" @@ -28,13 +25,6 @@ class Test_Stackless: - def setup_method(self, method): - # there is still a bug in stackless_new - # that requires to reinitialize the module - # for every test - if withinit: - stackless._init() - def test_simple(self): rlist = [] @@ -79,6 +69,7 @@ stackless.run() assert len(rlist) == 20 + print rlist for i in range(10): (s,r), rlist = rlist[:2], rlist[2:] assert s == 's%s' % i @@ -458,6 +449,79 @@ r = stackless.schedule('test') assert r == 'test' + def test_simple_pipe(self): + pypy_skip('should not fail, but does') + def pipe(X_in, X_out): + foo = X_in.receive() + X_out.send(foo) + + X, Y = stackless.channel(), stackless.channel() + stackless.tasklet(pipe)(X, Y) + stackless.run() + X.send(42) + assert Y.receive() == 42 + + def test_nested_pipe(self): + pypy_skip('should not fail, but does') + from stackless import run, tasklet, channel + + def pipe(X, Y): + foo = X.receive() + Y.send(foo) + + def nest(X, Y): + X2, Y2 = stackless.channel(), stackless.channel() + stackless.tasklet(pipe)(X2, Y2) + X2.send(X.receive()) + Y.send(Y2.receive()) + + X, Y = stackless.channel(), stackless.channel() + stackless.tasklet(nest)(X, Y) + X.send(42) + assert Y.receive() == 42 + + def test_wait_two(self): + """ + A tasklets/channels adaptation of the test_wait_two from the + logic object space + """ + pypy_skip('should not fail, but does') + + def sleep(X, Barrier): + Barrier.send((X, X.receive())) + + def wait_two(X, Y, Ret_chan): + Barrier = stackless.channel() + stackless.tasklet(sleep)(X, Barrier) + stackless.tasklet(sleep)(Y, Barrier) + ret = Barrier.receive() + if ret[0] == X: + Ret_chan.send((1, ret[1])) + return Ret_chan.send((2, ret[1])) + + X, Y, Ret_chan = stackless.channel(), stackless.channel(), stackless.channel() + stackless.tasklet(wait_two)(X, Y, Ret_chan) + Y.send(42) + X.send(42) + assert Ret_chan.receive() == (2, 42) + + def test_noop(self): + """ + this test is from pypy/lib/test2. + Left it in for documentation purposes. + "switch" is not officially in the tasklet interface. It it just + an implementation detail, that tasklets are descendents from + coroutines, which do have a 'switch' method + """ + skip("this test does not make sense at the moment") + main = stackless.getcurrent() + + def switch_to_main(): + main.switch() + + t = stackless.tasklet(switch_to_main)() + stackless.run() + Modified: pypy/dist/pypy/lib/stackless_new.py ============================================================================== --- pypy/dist/pypy/lib/stackless_new.py (original) +++ pypy/dist/pypy/lib/stackless_new.py Wed Dec 20 19:18:39 2006 @@ -18,6 +18,11 @@ from collections import deque +import operator +def deque_remove(dq, value): + "deque.remove is only in python2.5" + del dq[operator.indexOf(dq, value)] + __all__ = 'run getcurrent getmain schedule tasklet channel coroutine \ TaskletExit greenlet'.split() @@ -81,11 +86,13 @@ #receiver.tempval = sender.tempval receiver.tempval = sender.tempval squeue.append(sender) + #schedule() else: # nobody is waiting self.balance -= 1 - squeue.pop() + #squeue.pop() + #deque_remove(receiver) self.queue.append(receiver) - schedule() + schedule_remove() msg = receiver.tempval return msg @@ -218,6 +225,8 @@ Please note that the 'timeout' feature is not yet implemented """ schedule_remove() + while squeue: + schedule() scall = 0 @@ -228,14 +237,9 @@ tasklet as default. schedule_remove(retval=stackless.current) -- ditto, and remove self. """ - global first_run - if first_run: - squeue.rotate(-1) - first_run = False - t = squeue.pop() - if t is not getcurrent(): - squeue.appendleft(t) - + try: + deque_remove(squeue, getcurrent()) + except:pass schedule() def schedule(retval=None): @@ -247,16 +251,12 @@ """ mtask = getmain() - global first_run - if first_run: - squeue.rotate(-1) - first_run = False - if squeue: task = squeue[0] squeue.rotate(-1) - if task is not getcurrent() and task.is_alive: - task.switch() + curr = getcurrent() + if task is not curr and task.is_alive: + r = task.switch() curr = getcurrent() if not task.is_alive: if squeue: @@ -269,13 +269,20 @@ if curr is not mtask: mtask.switch() schedule() + elif task is curr: + if len(squeue) > 1: + schedule() + elif not task.is_alive: + try: + deque_remove(squeue, task) + except:pass + if not squeue: + squeue.append(mtask) def _init(): global main_tasklet global global_task_id - global first_run global squeue - first_run = True global_task_id = 0 main_tasklet = coroutine.getcurrent() try: From ericvrp at codespeak.net Wed Dec 20 21:46:47 2006 From: ericvrp at codespeak.net (ericvrp at codespeak.net) Date: Wed, 20 Dec 2006 21:46:47 +0100 (CET) Subject: [pypy-svn] r35923 - in pypy/dist/pypy/jit/codegen/llvm: . test Message-ID: <20061220204647.43A7910097@code0.codespeak.net> Author: ericvrp Date: Wed Dec 20 21:46:45 2006 New Revision: 35923 Modified: pypy/dist/pypy/jit/codegen/llvm/rgenop.py pypy/dist/pypy/jit/codegen/llvm/test/test_genc_ts.py Log: jit/codegen/llvm - dump info in the logfile just before an assert - fixed typo in log command - gave IntConst it's own operand methods because for a reason don't understand the const.value changes type??? - 10 more genc_ts tests passing Modified: pypy/dist/pypy/jit/codegen/llvm/rgenop.py ============================================================================== --- pypy/dist/pypy/jit/codegen/llvm/rgenop.py (original) +++ pypy/dist/pypy/jit/codegen/llvm/rgenop.py Wed Dec 20 21:46:45 2006 @@ -96,8 +96,8 @@ class GenericConst(GenConst): #type = 'generic' - def __init__(self, value): - self.value = value + #def __init__(self, value): + # self.value = value def operand(self): return '%s %s' % (self.type, self.value) @@ -118,6 +118,9 @@ class BoolConst(GenericConst): type = 'bool' + def __init__(self, value): + self.value = bool(value) + class CharConst(GenericConst): type = 'ubyte' @@ -126,24 +129,44 @@ if type(value) is str: self.value = ord(value) else: + assert type(value) is int self.value = value class UniCharConst(GenericConst): type = 'int' + def __init__(self, value): + self.value = unicode(value) + class IntConst(GenericConst): type = 'int' + def __init__(self, value): + self.value = int(value) + + #XXX why does typeof value change in test_genc_ts.py -k test_degenerated_before_return(_2)? + def operand(self): + return '%s %d' % (self.type, int(self.value)) + + def operand2(self): + return str(int(self.value)) + class UIntConst(GenericConst): type = 'uint' + def __init__(self, value): + self.value = int(value) + class FloatConst(GenericConst): type = 'float' + def __init__(self, value): + self.value = float(value) + class AddrConst(GenConst): type = 'int*' @@ -166,7 +189,9 @@ elif T is lltype.Signed: return llmemory.cast_adr_to_int(self.addr) else: - assert 0, "XXX not implemented" + msg = 'XXX not implemented' + logger.dump(msg) + assert 0, msg class Block(GenLabel): @@ -195,7 +220,10 @@ # check the types for debugging sourcevartypes = [var.type for var in sourcevars] targetvartypes = [var.type for var in self.inputargs] - assert sourcevartypes == targetvartypes + if sourcevartypes != targetvartypes: + logger.dump('sourcevartypes(%s) != targetvartypes(%s)' % ( + sourcevartypes, targetvartypes)) + assert sourcevartypes == targetvartypes # Check if the source block jumps to 'self' from multiple # positions: in this case we need an intermediate block... @@ -560,7 +588,7 @@ def op_float_is_true(self, gv_x): return self._is_true(gv_x, '0.0') def genop_getfield(self, (offset, fieldsize), gv_ptr): - log('%s Builder.genop_getfield ([%d]%d) %s' % ( + log('%s Builder.genop_getfield (%d,%d) %s' % ( self.block.label, offset, fieldsize, gv_ptr.operand())) if fieldsize == WORD: t = 'int' @@ -568,7 +596,9 @@ if fieldsize == 1: t = 'ubyte' else: - assert fieldsize == 2 + if fieldsize != 2: + logger.dump('fieldsize != [124]') + assert fieldsize == 2 t = 'short' gv_ptr_var = self._as_var(gv_ptr) gv_p = Var(t + '*') @@ -580,7 +610,7 @@ return gv_result def genop_setfield(self, (offset, fieldsize), gv_ptr, gv_value): - log('%s Builder.senop_setfield %s,([%d]%d) %s=%s' % ( + log('%s Builder.senop_setfield (%d,%d) %s=%s' % ( self.block.label, offset, fieldsize, gv_ptr.operand(), gv_value.operand())) #if fieldsize == WORD: # gv_result = Var('int') @@ -589,7 +619,7 @@ # gv_result = Var('ubyte') # else: # assert fieldsize == 2 - # gv_result = Var('short') + # gv_result = Var('short') gv_ptr_var = self._as_var(gv_ptr) gv_p = Var(gv_value.type+'*') self.asm.append(' %s=getelementptr %s,int %s' % ( @@ -597,8 +627,8 @@ self.asm.append(' store %s,%s' % ( gv_value.operand2(), gv_p.operand())) - def XXXgenop_getsubstruct(self, (offset, fieldsize), gv_ptr): - log('%s Builder.genop_getsubstruct [%d]%d,%s' % ( + def genop_getsubstruct(self, (offset, fieldsize), gv_ptr): + log('%s Builder.genop_getsubstruct (%d,%d) %s' % ( self.block.label, offset, fieldsize, gv_ptr.operand())) gv_ptr_var = self._as_var(gv_ptr) gv_sub = Var(gv_ptr.type) @@ -834,7 +864,9 @@ # self.keepalive_gc_refs.append(lltype.cast_opaque_ptr(llmemory.GCREF, llvalue)) return AddrConst(lladdr) else: - assert 0, "XXX not implemented" + msg = 'XXX not implemented' + logger.dump(msg) + assert 0, msg # attached later constPrebuiltGlobal = global_rgenop.genconst @@ -914,10 +946,11 @@ elif isinstance(T, lltype.Ptr): return llmemory.GCREF else: - assert 0, "XXX not implemented" + msg = 'XXX not implemented' + logger.dump(msg) + assert 0, msg global_rgenop = RLLVMGenOp() RLLVMGenOp.constPrebuiltGlobal = global_rgenop.genconst - 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 Wed Dec 20 21:46:45 2006 @@ -51,27 +51,27 @@ test_simple_struct = skip test_simple_array = skip test_setarrayitem = skip + test_degenerated_before_return = skip + test_degenerated_before_return_2 = skip + test_degenerated_via_substructure = skip + test_red_virtual_container = skip + test_red_propagate = skip + test_red_subcontainer = skip + test_red_subcontainer_cast = skip + test_merge_structures = skip + test_simple_meth = skip + test_simple_red_meth = skip #failing... if skip_failing: - test_degenerated_before_return = skip - test_degenerated_before_return_2 = skip test_degenerated_at_return = skip - test_degenerated_via_substructure = skip test_degenerate_with_voids = skip - test_red_virtual_container = skip test_red_array = skip test_red_struct_array = skip test_red_varsized_struct = skip test_array_of_voids = skip - test_red_propagate = skip - test_red_subcontainer = skip - test_red_subcontainer_cast = skip - test_merge_structures = skip test_green_with_side_effects = skip test_recursive_with_red_termination_condition = skip - test_simple_meth = skip - test_simple_red_meth = skip test_compile_time_const_tuple = skip test_residual_red_call = skip test_residual_red_call_with_exc = skip From stephan at codespeak.net Thu Dec 21 11:33:26 2006 From: stephan at codespeak.net (stephan at codespeak.net) Date: Thu, 21 Dec 2006 11:33:26 +0100 (CET) Subject: [pypy-svn] r35926 - in pypy/dist/pypy/lib: . app_test Message-ID: <20061221103326.46A8E10097@code0.codespeak.net> Author: stephan Date: Thu Dec 21 11:33:22 2006 New Revision: 35926 Modified: pypy/dist/pypy/lib/app_test/test_stackless.py pypy/dist/pypy/lib/stackless_new.py Log: fixed some issues with channel handling. There is still some issue with scheduling. Modified: pypy/dist/pypy/lib/app_test/test_stackless.py ============================================================================== --- pypy/dist/pypy/lib/app_test/test_stackless.py (original) +++ pypy/dist/pypy/lib/app_test/test_stackless.py Thu Dec 21 11:33:22 2006 @@ -450,7 +450,6 @@ assert r == 'test' def test_simple_pipe(self): - pypy_skip('should not fail, but does') def pipe(X_in, X_out): foo = X_in.receive() X_out.send(foo) @@ -462,21 +461,18 @@ assert Y.receive() == 42 def test_nested_pipe(self): - pypy_skip('should not fail, but does') - from stackless import run, tasklet, channel - def pipe(X, Y): foo = X.receive() Y.send(foo) def nest(X, Y): X2, Y2 = stackless.channel(), stackless.channel() - stackless.tasklet(pipe)(X2, Y2) + t = stackless.tasklet(pipe)(X2, Y2) X2.send(X.receive()) Y.send(Y2.receive()) X, Y = stackless.channel(), stackless.channel() - stackless.tasklet(nest)(X, Y) + t1 = stackless.tasklet(nest)(X, Y) X.send(42) assert Y.receive() == 42 @@ -485,8 +481,11 @@ A tasklets/channels adaptation of the test_wait_two from the logic object space """ - pypy_skip('should not fail, but does') - + # there are still problems with scheduling. Apparently, + # some leftover tasklets in the queue are messing + # things up. This test runs fine, when being alone + # in a test file + pypy_skip("still problems with scheduling") def sleep(X, Barrier): Barrier.send((X, X.receive())) @@ -497,13 +496,15 @@ ret = Barrier.receive() if ret[0] == X: Ret_chan.send((1, ret[1])) - return Ret_chan.send((2, ret[1])) + else: + Ret_chan.send((2, ret[1])) X, Y, Ret_chan = stackless.channel(), stackless.channel(), stackless.channel() stackless.tasklet(wait_two)(X, Y, Ret_chan) Y.send(42) X.send(42) - assert Ret_chan.receive() == (2, 42) + value = Ret_chan.receive() + assert value == (2, 42) def test_noop(self): """ Modified: pypy/dist/pypy/lib/stackless_new.py ============================================================================== --- pypy/dist/pypy/lib/stackless_new.py (original) +++ pypy/dist/pypy/lib/stackless_new.py Thu Dec 21 11:33:22 2006 @@ -19,9 +19,24 @@ from collections import deque import operator -def deque_remove(dq, value): - "deque.remove is only in python2.5" - del dq[operator.indexOf(dq, value)] +def _scheduler_remove(value): + try: + del squeue[operator.indexOf(squeue, value)] + except ValueError:pass + +def _scheduler_append(value, normal=True): + if normal: + squeue.append(value) + else: + squeue.appendleft(value) + +def _scheduler_contains(value): + try: + operator.indexOf(squeue, value) + return True + except ValueError: + return False + __all__ = 'run getcurrent getmain schedule tasklet channel coroutine \ TaskletExit greenlet'.split() @@ -83,15 +98,13 @@ if self.balance > 0: # somebody is already sending self.balance -= 1 sender = self.queue.popleft() - #receiver.tempval = sender.tempval + sender.blocked = False receiver.tempval = sender.tempval - squeue.append(sender) - #schedule() + _scheduler_append(sender) else: # nobody is waiting self.balance -= 1 - #squeue.pop() - #deque_remove(receiver) self.queue.append(receiver) + receiver.blocked = True schedule_remove() msg = receiver.tempval return msg @@ -108,12 +121,14 @@ sender.tempval = msg if self.balance < 0: # somebody is already waiting receiver = self.queue.popleft() + receiver.blocked = False self.balance += 1 receiver.tempval = msg - squeue.appendleft(receiver) + _scheduler_append(receiver, False) schedule() else: # nobody is waiting - self.queue.append(squeue[-1]) + self.queue.append(sender) + sender.blocked = True self.balance += 1 schedule_remove() @@ -135,6 +150,7 @@ global global_task_id self.tempval = func self.alive = False + self.blocked = False self.task_id = global_task_id global_task_id += 1 @@ -180,7 +196,7 @@ coroutine.bind(self,self.tempval,*argl,**argd) self.tempval = None self.alive = True - squeue.append(self) + _scheduler_append(self) return self def __reduce__(self): @@ -228,8 +244,6 @@ while squeue: schedule() -scall = 0 - def schedule_remove(retval=None): """ schedule(retval=stackless.current) -- switch to the next runnable tasklet. @@ -237,9 +251,7 @@ tasklet as default. schedule_remove(retval=stackless.current) -- ditto, and remove self. """ - try: - deque_remove(squeue, getcurrent()) - except:pass + _scheduler_remove(getcurrent()) schedule() def schedule(retval=None): @@ -262,7 +274,7 @@ if squeue: pt = squeue.pop() if pt.is_alive: - squeue.append(pt) + _scheduler_append(pt) else: coroutine.kill(task) else: @@ -271,13 +283,13 @@ schedule() elif task is curr: if len(squeue) > 1: + if squeue[0] is squeue[-1]: + squeue.pop() schedule() elif not task.is_alive: - try: - deque_remove(squeue, task) - except:pass + _scheduler_remove(task) if not squeue: - squeue.append(mtask) + _scheduler_append(mtask) def _init(): global main_tasklet @@ -312,6 +324,6 @@ assert main_tasklet.is_alive and not main_tasklet.is_zombie tasklet._init(main_tasklet) squeue = deque() - squeue.append(main_tasklet) + _scheduler_append(main_tasklet) _init() From guido at codespeak.net Thu Dec 21 11:55:00 2006 From: guido at codespeak.net (guido at codespeak.net) Date: Thu, 21 Dec 2006 11:55:00 +0100 (CET) Subject: [pypy-svn] r35927 - in pypy/dist/pypy/tool/build: . test Message-ID: <20061221105500.7BD691008E@code0.codespeak.net> Author: guido Date: Thu Dec 21 11:54:58 2006 New Revision: 35927 Modified: pypy/dist/pypy/tool/build/build.py pypy/dist/pypy/tool/build/client.py pypy/dist/pypy/tool/build/test/test_client.py pypy/dist/pypy/tool/build/test/test_server.py Log: Fixed broken test (sorry!), some small cleanups and docstrings and such. Modified: pypy/dist/pypy/tool/build/build.py ============================================================================== --- pypy/dist/pypy/tool/build/build.py (original) +++ pypy/dist/pypy/tool/build/build.py Thu Dec 21 11:54:58 2006 @@ -23,6 +23,20 @@ return int(u.info().created_rev) class BuildPath(LocalPath): + """ a subclass from py.path.local that has some additional properties + + * BuildPath.request holds the request object + + * BuildPath.zipfile returns a zip file (path object) with the build + results (if available) + + * BuildPath.log has the log of the build (if available) + + * BuildPath.done indicates whether the build is done or still in + progress + + """ + def _request(self): req = self.join('request') if not req.check(): @@ -63,12 +77,6 @@ return not not self.log done = property(_done) -class Build(object): - """ build data """ - def __init__(self, buildrequest, buildpath): - self.request = buildrequest - self.path = buildpath - class BuildRequest(object): """ build request data Modified: pypy/dist/pypy/tool/build/client.py ============================================================================== --- pypy/dist/pypy/tool/build/client.py (original) +++ pypy/dist/pypy/tool/build/client.py Thu Dec 21 11:54:58 2006 @@ -57,9 +57,7 @@ buildpath.log = self.channel.receive() else: # pretend we're compiling by sleeping a bit... - open('/tmp/test_client_functional_crap', 'a').write('CLIENT - starting compile, sleeping %r secs\n' % (self.testing_sleeptime,)) py.std.time.sleep(self.testing_sleeptime) - open('/tmp/test_client_functional_crap', 'a').write('CLIENT - done with compile\n') self.server.compilation_done(buildpath) self.busy_on = None @@ -123,11 +121,8 @@ def flush(self): pass -def zip_result(res_dir, channel): - channelwrapper = ChannelWrapper(channel) - zip = ZipFile(channelwrapper, 'w') - # might not be C pypy... - # zip.writestr('pypy-c', res_dir.join('testing_1/testing_1').read()) +def zip_dir(res_dir, tofile): + zip = ZipFile(tofile, 'w') for fpath in res_dir.visit(): try: zip.writestr(fpath.relto(res_dir), fpath.read()) @@ -135,7 +130,6 @@ print exc continue zip.close() - channelwrapper.close() def tempdir(parent=None): i = 0 @@ -148,6 +142,7 @@ i += 1 def main(config, path, compilefunc): + """ client bootstrapping and main loop """ from py.execnet import SshGateway, PopenGateway if config.server in ['localhost', '127.0.0.1']: @@ -166,21 +161,20 @@ while 1: # receive compile requests request = channel.receive() - if isinstance(request, str): - try: - request = build.BuildRequest.fromstring(request) - except (KeyError, SyntaxError), e: - print ('exception occurred when trying to ' - 'interpret the following request:') - print request - print - print 'going to continue' - continue - else: + if not isinstance(request, str): raise ValueError( 'received wrong unexpected data of type %s' % ( type(request),) ) + try: + request = build.BuildRequest.fromstring(request) + except (KeyError, SyntaxError), e: + print ('exception occurred when trying to ' + 'interpret the following request:') + print request + print + print 'going to continue' + continue accepting = True for checker in config.client_checkers: if not checker(request): @@ -196,7 +190,7 @@ if not accepting: print 'refusing compilation' continue - # XXX we should compile here, using data dict for info + print 'compilation requested for %s' % (request,) # subversion checkout @@ -217,7 +211,9 @@ if upath: # send over zip data, end with a None print 'compilation successful, sending to server' - zip_result(py.path.local(upath), channel) + wrapper = ChannelWrapper(channel) + zip_dir(py.path.local(upath), wrapper) + wrapper.close() else: print 'compilation failed, notifying server' # just send the None Modified: pypy/dist/pypy/tool/build/test/test_client.py ============================================================================== --- pypy/dist/pypy/tool/build/test/test_client.py (original) +++ pypy/dist/pypy/tool/build/test/test_client.py Thu Dec 21 11:54:58 2006 @@ -82,19 +82,13 @@ assert br in c1.refused assert c1.busy_on == None -def test_zip_result(): - channel = FakeChannel() - tempdir = py.test.ensuretemp('zip_result') +def test_zip_dir(): + tempdir = py.test.ensuretemp('zip_dir') tempdir.mkdir('foo') tempdir.join('foo/bar.txt').write('bar') - client.zip_result(tempdir, channel) zip = StringIO() - while 1: - chunk = channel.receive() - if chunk is None: - break - zip.write(chunk) + client.zip_dir(tempdir, zip) zip.seek(0) zf = ZipFile(zip) Modified: pypy/dist/pypy/tool/build/test/test_server.py ============================================================================== --- pypy/dist/pypy/tool/build/test/test_server.py (original) +++ pypy/dist/pypy/tool/build/test/test_server.py Thu Dec 21 11:54:58 2006 @@ -53,6 +53,8 @@ assert ret[1].find('found a suitable client') > -1 ret = svr._channel.receive() assert ret.find('going to send compile job') > -1 + acceptedmsg = svr._channel.receive() + assert acceptedmsg == 'compile job accepted' ret = c1.channel.receive() assert ret == br.serialize() none = c1.channel.receive() @@ -70,6 +72,8 @@ svr.compile(br3) ret = svr._channel.receive() assert ret.find('going to send') > -1 + acceptedmsg = svr._channel.receive() + assert acceptedmsg == 'compile job accepted' assert c2.channel.receive() == br3.serialize() assert c2.channel.receive() is None py.test.raises(IndexError, "c1.channel.receive()") From stephan at codespeak.net Thu Dec 21 12:02:49 2006 From: stephan at codespeak.net (stephan at codespeak.net) Date: Thu, 21 Dec 2006 12:02:49 +0100 (CET) Subject: [pypy-svn] r35928 - in pypy/dist/pypy/lib: . app_test Message-ID: <20061221110249.EE32110097@code0.codespeak.net> Author: stephan Date: Thu Dec 21 12:02:48 2006 New Revision: 35928 Modified: pypy/dist/pypy/lib/app_test/test_stackless.py pypy/dist/pypy/lib/stackless_new.py Log: added support for schedule_callback and channel_callback. schedule_callback is not behaving as in CStackless and I'm not entirely sure, if it were possible with new implementation (since 'coroutine.finished' is not longer used) Modified: pypy/dist/pypy/lib/app_test/test_stackless.py ============================================================================== --- pypy/dist/pypy/lib/app_test/test_stackless.py (original) +++ pypy/dist/pypy/lib/app_test/test_stackless.py Thu Dec 21 12:02:48 2006 @@ -328,7 +328,6 @@ ('schedule', 1), ('schedule', 2),] def test_channel_callback(self): - pypy_skip('not yet implemented in pypy') res = [] cb = [] def callback_function(chan, task, sending, willblock): @@ -354,7 +353,12 @@ ] def test_schedule_callback(self): - pypy_skip('not yet implemented in pypy') + pypy_skip('not running correctly') + # in stackless_new, a dead tasklet will be removed + # and is not known anymore when scheduling happens. + # Due to the applevel nature of stackless_new, + # the schedule callback is done only on explicit schedule, + # but not on implicit ones res = [] cb = [] def schedule_cb(prev, next): @@ -371,13 +375,11 @@ maintask = stackless.getmain() stackless.run() assert res == ['A_1', 'A_2', 'B_1', 'B_2'] - assert cb == [ - (maintask, t1), - (t1, t2), - (t2, t1), - (t1, t2), - (t2, maintask) - ] + assert cb[0] == (maintask, t1) + assert cb[1] == (t1, t2) + assert cb[2] == (t2, t1) + assert cb[3] == (t1, t2) + assert cb[4] == (t2, maintask) def test_bomb(self): pypy_skip('not yet implemented in pypy') Modified: pypy/dist/pypy/lib/stackless_new.py ============================================================================== --- pypy/dist/pypy/lib/stackless_new.py (original) +++ pypy/dist/pypy/lib/stackless_new.py Thu Dec 21 12:02:48 2006 @@ -19,6 +19,17 @@ from collections import deque import operator +__all__ = 'run getcurrent getmain schedule tasklet channel coroutine \ + TaskletExit greenlet'.split() + +global_task_id = 0 +squeue = None +main_tasklet = None +main_coroutine = None +first_run = False +_channel_callback = None +_schedule_callback = None + def _scheduler_remove(value): try: del squeue[operator.indexOf(squeue, value)] @@ -37,18 +48,22 @@ except ValueError: return False +def _scheduler_switch(current, next): + if _schedule_callback is not None: + _schedule_callback(current, next) + return next.switch() -__all__ = 'run getcurrent getmain schedule tasklet channel coroutine \ - TaskletExit greenlet'.split() - -global_task_id = 0 -squeue = None -main_tasklet = None -main_coroutine = None -first_run = False class TaskletExit(Exception):pass +def set_schedule_callback(callback): + global _schedule_callback + _schedule_callback = callback + +def set_channel_callback(callback): + global _channel_callback + _channel_callback = callback + class channel(object): """ A channel object is used for communication between tasklets. @@ -95,6 +110,9 @@ The above policy can be changed by setting channel flags. """ receiver = getcurrent() + willblock = not self.balance > 0 + if _channel_callback is not None: + _channel_callback(self, receiver, 0, willblock) if self.balance > 0: # somebody is already sending self.balance -= 1 sender = self.queue.popleft() @@ -119,6 +137,9 @@ """ sender = getcurrent() sender.tempval = msg + willblock = not self.balance < 0 + if _channel_callback is not None: + _channel_callback(self, sender, 1, willblock) if self.balance < 0: # somebody is already waiting receiver = self.queue.popleft() receiver.blocked = False @@ -268,7 +289,8 @@ squeue.rotate(-1) curr = getcurrent() if task is not curr and task.is_alive: - r = task.switch() + #r = task.switch() + r = _scheduler_switch(curr, task) curr = getcurrent() if not task.is_alive: if squeue: @@ -279,7 +301,8 @@ coroutine.kill(task) else: if curr is not mtask: - mtask.switch() + r = _scheduler_switch(curr, mtask) + #mtask.switch() schedule() elif task is curr: if len(squeue) > 1: From stephan at codespeak.net Thu Dec 21 15:09:01 2006 From: stephan at codespeak.net (stephan at codespeak.net) Date: Thu, 21 Dec 2006 15:09:01 +0100 (CET) Subject: [pypy-svn] r35931 - in pypy/dist/pypy/lib: . app_test Message-ID: <20061221140901.8436810086@code0.codespeak.net> Author: stephan Date: Thu Dec 21 15:09:00 2006 New Revision: 35931 Modified: pypy/dist/pypy/lib/app_test/test_stackless.py pypy/dist/pypy/lib/stackless_new.py Log: passing now all tests but one. But 'schedule' looks more and more terrible. Sigh.... Anyway, stackless_new.py has less than half the lines than stackless.py which I'd call an improvement Modified: pypy/dist/pypy/lib/app_test/test_stackless.py ============================================================================== --- pypy/dist/pypy/lib/app_test/test_stackless.py (original) +++ pypy/dist/pypy/lib/app_test/test_stackless.py Thu Dec 21 15:09:00 2006 @@ -69,7 +69,6 @@ stackless.run() assert len(rlist) == 20 - print rlist for i in range(10): (s,r), rlist = rlist[:2], rlist[2:] assert s == 's%s' % i @@ -225,7 +224,6 @@ def test_simple_channel(self): output = [] - #skip('') def print_(*args): output.append(args) @@ -353,12 +351,6 @@ ] def test_schedule_callback(self): - pypy_skip('not running correctly') - # in stackless_new, a dead tasklet will be removed - # and is not known anymore when scheduling happens. - # Due to the applevel nature of stackless_new, - # the schedule callback is done only on explicit schedule, - # but not on implicit ones res = [] cb = [] def schedule_cb(prev, next): @@ -382,19 +374,17 @@ assert cb[4] == (t2, maintask) def test_bomb(self): - pypy_skip('not yet implemented in pypy') try: 1/0 except: import sys b = stackless.bomb(*sys.exc_info()) assert b.type is ZeroDivisionError - print type(b.value) - assert str(b.value) == 'integer division or modulo by zero' + print str(b.value) + assert str(b.value).startswith('integer division') assert b.traceback is not None def test_send_exception(self): - pypy_skip('not yet implemented in pypy') def exp_sender(chan): chan.send_exception(Exception, 'test') @@ -411,7 +401,6 @@ stackless.run() def test_send_sequence(self): - pypy_skip('not yet implemented in pypy') res = [] lst = [1,2,3,4,5,6,None] iterable = iter(lst) @@ -427,7 +416,6 @@ assert res == [1,2,3,4,5,6] def test_getruncount(self): - pypy_skip('not yet implemented in pypy') assert stackless.getruncount() == 1 def with_schedule(): assert stackless.getruncount() == 2 @@ -442,7 +430,6 @@ stackless.run() def test_schedule_return(self): - pypy_skip('not yet implemented in pypy') def f():pass t1= stackless.tasklet(f)() r = stackless.schedule() Modified: pypy/dist/pypy/lib/stackless_new.py ============================================================================== --- pypy/dist/pypy/lib/stackless_new.py (original) +++ pypy/dist/pypy/lib/stackless_new.py Thu Dec 21 15:09:00 2006 @@ -22,36 +22,39 @@ __all__ = 'run getcurrent getmain schedule tasklet channel coroutine \ TaskletExit greenlet'.split() -global_task_id = 0 -squeue = None -main_tasklet = None -main_coroutine = None -first_run = False +_global_task_id = 0 +_squeue = None +_main_tasklet = None +_main_coroutine = None +_last_task = None _channel_callback = None _schedule_callback = None def _scheduler_remove(value): try: - del squeue[operator.indexOf(squeue, value)] + del _squeue[operator.indexOf(_squeue, value)] except ValueError:pass def _scheduler_append(value, normal=True): if normal: - squeue.append(value) + _squeue.append(value) else: - squeue.appendleft(value) + _squeue.appendleft(value) def _scheduler_contains(value): try: - operator.indexOf(squeue, value) + operator.indexOf(_squeue, value) return True except ValueError: return False def _scheduler_switch(current, next): + global _last_task + _last_task = next if _schedule_callback is not None: _schedule_callback(current, next) - return next.switch() + next.switch() + return current class TaskletExit(Exception):pass @@ -64,6 +67,18 @@ global _channel_callback _channel_callback = callback +def getruncount(): + return len(_squeue) + +class bomb(object): + def __init__(self, exp_type=None, exp_value=None, exp_traceback=None): + self.type = exp_type + self.value = exp_value + self.traceback = exp_traceback + + def raise_(self): + raise self.type(self.value) + class channel(object): """ A channel object is used for communication between tasklets. @@ -125,8 +140,17 @@ receiver.blocked = True schedule_remove() msg = receiver.tempval + if isinstance(msg, bomb): + msg.raise_() return msg + def send_exception(self, exp_type, msg): + self.send(bomb(exp_type, exp_type(msg))) + + def send_sequence(self, iterable): + for item in iterable: + self.send(item) + def send(self, msg): """ channel.send(value) -- send a value over the channel. @@ -168,16 +192,15 @@ self._init(func) def _init(self, func=None): - global global_task_id + global _global_task_id self.tempval = func self.alive = False self.blocked = False - self.task_id = global_task_id - global_task_id += 1 + self.task_id = _global_task_id + _global_task_id += 1 def __str__(self): - return '' % \ - (self.task_id, self.is_alive, self.is_zombie) + return '' % (self.task_id, self.is_alive) __repr__ = __str__ @@ -235,7 +258,7 @@ """ getmain() -- return the main tasklet. """ - return main_tasklet + return _main_tasklet def getcurrent(): """ @@ -243,8 +266,8 @@ """ curr = coroutine.getcurrent() - if curr is main_coroutine: - return main_tasklet + if curr is _main_coroutine: + return _main_tasklet else: return curr @@ -261,9 +284,12 @@ Please note that the 'timeout' feature is not yet implemented """ - schedule_remove() - while squeue: - schedule() + r = schedule_remove() + if _last_task and _schedule_callback is not None: + _schedule_callback(_last_task, getcurrent()) + while _squeue: + r = schedule() + _scheduler_append(getcurrent()) def schedule_remove(retval=None): """ @@ -273,28 +299,28 @@ schedule_remove(retval=stackless.current) -- ditto, and remove self. """ _scheduler_remove(getcurrent()) - schedule() + r = schedule(retval) + return r -def schedule(retval=None): +def schedule(retval=None, prev=None): """ schedule(retval=stackless.current) -- switch to the next runnable tasklet. The return value for this call is retval, with the current tasklet as default. schedule_remove(retval=stackless.current) -- ditto, and remove self. """ - mtask = getmain() - if squeue: - task = squeue[0] - squeue.rotate(-1) - curr = getcurrent() + curr = getcurrent() + if _squeue: + task = _squeue[0] + _squeue.rotate(-1) if task is not curr and task.is_alive: - #r = task.switch() - r = _scheduler_switch(curr, task) + c = prev or curr + r = _scheduler_switch(c, task) curr = getcurrent() if not task.is_alive: - if squeue: - pt = squeue.pop() + if _squeue: + pt = _squeue.pop() if pt.is_alive: _scheduler_append(pt) else: @@ -302,29 +328,36 @@ else: if curr is not mtask: r = _scheduler_switch(curr, mtask) - #mtask.switch() - schedule() + return retval or r + r = schedule(prev=task) + return retval or r + return r elif task is curr: - if len(squeue) > 1: - if squeue[0] is squeue[-1]: - squeue.pop() - schedule() + if len(_squeue) > 1: + if _squeue[0] is _squeue[-1]: + _squeue.pop() + r = schedule() + return retval or r + return retval or curr elif not task.is_alive: _scheduler_remove(task) - if not squeue: + if not _squeue: _scheduler_append(mtask) + return retval or curr + return retval or curr def _init(): - global main_tasklet - global global_task_id - global squeue - global_task_id = 0 - main_tasklet = coroutine.getcurrent() + global _main_tasklet + global _global_task_id + global _squeue + global _last_task + _global_task_id = 0 + _main_tasklet = coroutine.getcurrent() try: - main_tasklet.__class__ = tasklet + _main_tasklet.__class__ = tasklet except TypeError: # we are running pypy-c class TaskletProxy(object): - """TaskletProxy is needed to give the main_coroutine tasklet behaviour""" + """TaskletProxy is needed to give the _main_coroutine tasklet behaviour""" def __init__(self, coro): self._coro = coro @@ -341,12 +374,12 @@ __repr__ = __str__ - global main_coroutine - main_coroutine = main_tasklet - main_tasklet = TaskletProxy(main_tasklet) - assert main_tasklet.is_alive and not main_tasklet.is_zombie - tasklet._init(main_tasklet) - squeue = deque() - _scheduler_append(main_tasklet) + global _main_coroutine + _main_coroutine = _main_tasklet + _main_tasklet = TaskletProxy(_main_tasklet) + assert _main_tasklet.is_alive and not _main_tasklet.is_zombie + tasklet._init(_main_tasklet) + _squeue = deque() + _scheduler_append(_main_tasklet) _init() From mwh at codespeak.net Thu Dec 21 15:59:06 2006 From: mwh at codespeak.net (mwh at codespeak.net) Date: Thu, 21 Dec 2006 15:59:06 +0100 (CET) Subject: [pypy-svn] r35932 - pypy/dist/pypy/translator/llvm/test Message-ID: <20061221145906.1A85210086@code0.codespeak.net> Author: mwh Date: Thu Dec 21 15:59:04 2006 New Revision: 35932 Added: pypy/dist/pypy/translator/llvm/test/test_rtagged.py - copied, changed from r35929, pypy/dist/pypy/translator/c/test/test_rtagged.py Log: add a skipped test for the tagged integer stuff on top of llvm. doesn't seem to be trivial to get working... From adim at codespeak.net Thu Dec 21 16:13:58 2006 From: adim at codespeak.net (adim at codespeak.net) Date: Thu, 21 Dec 2006 16:13:58 +0100 (CET) Subject: [pypy-svn] r35933 - in pypy/branch/ast-experiments/pypy/interpreter/pyparser: . test Message-ID: <20061221151358.9B12D1007E@code0.codespeak.net> Author: adim Date: Thu Dec 21 16:13:54 2006 New Revision: 35933 Added: pypy/branch/ast-experiments/pypy/interpreter/pyparser/asthelper.py Modified: pypy/branch/ast-experiments/pypy/interpreter/pyparser/astbuilder.py pypy/branch/ast-experiments/pypy/interpreter/pyparser/grammar.py pypy/branch/ast-experiments/pypy/interpreter/pyparser/pythonparse.py pypy/branch/ast-experiments/pypy/interpreter/pyparser/pythonutil.py pypy/branch/ast-experiments/pypy/interpreter/pyparser/test/test_astbuilder.py Log: - added a reference to the parser in AstBuilder, and tried to avoid using PYTHON_PARSER as much as possible. - split astbuilder.py in 2 modules Modified: pypy/branch/ast-experiments/pypy/interpreter/pyparser/astbuilder.py ============================================================================== --- pypy/branch/ast-experiments/pypy/interpreter/pyparser/astbuilder.py (original) +++ pypy/branch/ast-experiments/pypy/interpreter/pyparser/astbuilder.py Thu Dec 21 16:13:54 2006 @@ -1,519 +1,18 @@ """This module provides the astbuilder class which is to be used -by GrammarElements to directly build the AST during parsing +by GrammarElements to directly build the AS during parsing without going through the nested tuples step """ from grammar import BaseGrammarBuilder, AbstractContext + +from pypy.interpreter.function import Function from pypy.interpreter.astcompiler import ast, consts -from pypy.interpreter.pyparser import pythonparse -import pypy.interpreter.pyparser.pytoken as tok +# from pypy.interpreter.pyparser import pythonparse +#import pypy.interpreter.pyparser.pytoken as tok from pypy.interpreter.pyparser.error import SyntaxError from pypy.interpreter.pyparser.parsestring import parsestr -# XXX : use builder.parser instead -sym = pythonparse.PYTHON_PARSER.symbols -rsym = pythonparse.PYTHON_PARSER.symbol_repr -tok = pythonparse.PYTHON_PARSER - -### Parsing utilites ################################################# -def parse_except_clause(tokens): - """parses 'except' [test [',' test]] ':' suite - and returns a 4-tuple : (tokens_read, expr1, expr2, except_body) - """ - lineno = tokens[0].lineno - clause_length = 1 - # Read until end of except clause (bound by following 'else', - # or 'except' or end of tokens) - while clause_length < len(tokens): - token = tokens[clause_length] - if isinstance(token, TokenObject) and \ - (token.get_value() == 'except' or token.get_value() == 'else'): - break - clause_length += 1 - if clause_length == 3: - # case 'except: body' - return (3, None, None, tokens[2]) - elif clause_length == 4: - # case 'except Exception: body': - return (4, tokens[1], None, tokens[3]) - else: - # case 'except Exception, exc: body' - return (6, tokens[1], to_lvalue(tokens[3], consts.OP_ASSIGN), tokens[5]) - - -def parse_dotted_names(tokens): - """parses NAME('.' NAME)* and returns full dotted name - - this function doesn't assume that the list ends after the - last 'NAME' element - """ - first = tokens[0] - assert isinstance(first, TokenObject) - name = first.get_value() - l = len(tokens) - index = 1 - for index in range(1, l, 2): - token = tokens[index] - assert isinstance(token, TokenObject) - if token.name != tok.DOT: - break - token = tokens[index+1] - assert isinstance(token, TokenObject) - name += '.' - value = token.get_value() - name += value - return (index, name) - -def parse_argument(tokens): - """parses function call arguments""" - l = len(tokens) - index = 0 - arguments = [] - last_token = None - building_kw = False - kw_built = False - stararg_token = None - dstararg_token = None - while index < l: - cur_token = tokens[index] - if not isinstance(cur_token, TokenObject): - index += 1 - if not building_kw: - arguments.append(cur_token) - else: - last_token = arguments.pop() - assert isinstance(last_token, ast.Name) # used by rtyper - arguments.append(ast.Keyword(last_token.varname, cur_token, last_token.lineno)) - building_kw = False - kw_built = True - continue - elif cur_token.name == tok.COMMA: - index += 1 - continue - elif cur_token.name == tok.EQUAL: - index += 1 - building_kw = True - continue - elif cur_token.name == tok.STAR or cur_token.name == tok.DOUBLESTAR: - index += 1 - if cur_token.name == tok.STAR: - stararg_token = tokens[index] - index += 1 - if index >= l: - break - index += 2 # Skip COMMA and DOUBLESTAR - dstararg_token = tokens[index] - break - elif cur_token.get_value() == 'for': - if len(arguments) != 1: - raise SyntaxError("invalid syntax", cur_token.lineno, - cur_token.col) - expr = arguments[0] - genexpr_for = parse_genexpr_for(tokens[index:]) - genexpr_for[0].is_outmost = True - gexp = ast.GenExpr(ast.GenExprInner(expr, genexpr_for, expr.lineno), expr.lineno) - arguments[0] = gexp - break - return arguments, stararg_token, dstararg_token - - -def parse_fpdef(tokens, index): - """fpdef: fpdef: NAME | '(' fplist ')' - fplist: fpdef (',' fpdef)* [','] - - This intend to be a RPYTHON compliant implementation of _parse_fpdef, - but it can't work with the default compiler. - We switched to use astcompiler module now - """ - nodes = [] - comma = False - while True: - token = tokens[index] - index += 1 - assert isinstance(token, TokenObject) - if token.name == tok.LPAR: # nested item - index, node = parse_fpdef(tokens, index) - elif token.name == tok.RPAR: # end of current nesting - break - else: # name - val = token.get_value() - node = ast.AssName(val, consts.OP_ASSIGN, token.lineno) - nodes.append(node) - - token = tokens[index] - index += 1 - assert isinstance(token, TokenObject) - if token.name == tok.COMMA: - comma = True - else: - assert token.name == tok.RPAR - break - if len(nodes) == 1 and not comma: - node = nodes[0] - else: - node = ast.AssTuple(nodes, token.lineno) - return index, node - -def parse_arglist(tokens): - """returns names, defaults, flags""" - l = len(tokens) - index = 0 - defaults = [] - names = [] - flags = 0 - first_with_default = -1 - while index < l: - cur_token = tokens[index] - index += 1 - if not isinstance(cur_token, TokenObject): - # XXX: think of another way to write this test - defaults.append(cur_token) - if first_with_default == -1: - first_with_default = len(names) - 1 - elif cur_token.name == tok.COMMA: - # We could skip test COMMA by incrementing index cleverly - # but we might do some experiment on the grammar at some point - continue - elif cur_token.name == tok.LPAR: - index, node = parse_fpdef(tokens, index) - names.append(node) - elif cur_token.name == tok.STAR or cur_token.name == tok.DOUBLESTAR: - if cur_token.name == tok.STAR: - cur_token = tokens[index] - assert isinstance(cur_token, TokenObject) - index += 1 - if cur_token.name == tok.NAME: - val = cur_token.get_value() - names.append( ast.AssName( val, consts.OP_ASSIGN ) ) - flags |= consts.CO_VARARGS - index += 1 - if index >= l: - break - else: - # still more tokens to read - cur_token = tokens[index] - index += 1 - else: - raise SyntaxError("incomplete varags", cur_token.lineno, - cur_token.col) - assert isinstance(cur_token, TokenObject) - if cur_token.name != tok.DOUBLESTAR: - raise SyntaxError("Unexpected token", cur_token.lineno, - cur_token.col) - cur_token = tokens[index] - index += 1 - assert isinstance(cur_token, TokenObject) - if cur_token.name == tok.NAME: - val = cur_token.get_value() - names.append( ast.AssName( val, consts.OP_ASSIGN ) ) - flags |= consts.CO_VARKEYWORDS - index += 1 - else: - raise SyntaxError("incomplete varags", cur_token.lineno, - cur_token.col) - if index < l: - token = tokens[index] - raise SyntaxError("unexpected token" , token.lineno, - token.col) - elif cur_token.name == tok.NAME: - val = cur_token.get_value() - names.append( ast.AssName( val, consts.OP_ASSIGN ) ) - - if first_with_default != -1: - num_expected_with_default = len(names) - first_with_default - if flags & consts.CO_VARKEYWORDS: - num_expected_with_default -= 1 - if flags & consts.CO_VARARGS: - num_expected_with_default -= 1 - if len(defaults) != num_expected_with_default: - raise SyntaxError('non-default argument follows default argument', - tokens[0].lineno, tokens[0].col) - return names, defaults, flags - - -def parse_listcomp(tokens): - """parses 'for j in k for i in j if i %2 == 0' and returns - a GenExprFor instance - XXX: refactor with listmaker ? - """ - list_fors = [] - ifs = [] - index = 0 - if tokens: - lineno = tokens[0].lineno - else: - lineno = -1 - while index < len(tokens): - token = tokens[index] - assert isinstance(token, TokenObject) # rtyper info + check - if token.get_value() == 'for': - index += 1 # skip 'for' - ass_node = to_lvalue(tokens[index], consts.OP_ASSIGN) - index += 2 # skip 'in' - iterables = [tokens[index]] - index += 1 - while index < len(tokens): - tok2 = tokens[index] - if not isinstance(tok2, TokenObject): - break - if tok2.name != tok.COMMA: - break - iterables.append(tokens[index+1]) - index += 2 - if len(iterables) == 1: - iterable = iterables[0] - else: - iterable = ast.Tuple(iterables, token.lineno) - while index < len(tokens): - token = tokens[index] - assert isinstance(token, TokenObject) # rtyper info - if token.get_value() == 'if': - ifs.append(ast.ListCompIf(tokens[index+1], token.lineno)) - index += 2 - else: - break - list_fors.append(ast.ListCompFor(ass_node, iterable, ifs, lineno)) - ifs = [] - else: - assert False, 'Unexpected token: expecting for in listcomp' - # - # Original implementation: - # - # if tokens[index].get_value() == 'for': - # index += 1 # skip 'for' - # ass_node = to_lvalue(tokens[index], consts.OP_ASSIGN) - # index += 2 # skip 'in' - # iterable = tokens[index] - # index += 1 - # while index < len(tokens) and tokens[index].get_value() == 'if': - # ifs.append(ast.ListCompIf(tokens[index+1])) - # index += 2 - # list_fors.append(ast.ListCompFor(ass_node, iterable, ifs)) - # ifs = [] - # else: - # raise ValueError('Unexpected token: %s' % tokens[index]) - return list_fors - - -def parse_genexpr_for(tokens): - """parses 'for j in k for i in j if i %2 == 0' and returns - a GenExprFor instance - XXX: if RPYTHON supports to pass a class object to a function, - we could refactor parse_listcomp and parse_genexpr_for, - and call : - - parse_listcomp(tokens, forclass=ast.GenExprFor, ifclass=...) - or: - - parse_listcomp(tokens, forclass=ast.ListCompFor, ifclass=...) - """ - genexpr_fors = [] - ifs = [] - index = 0 - if tokens: - lineno = tokens[0].lineno - else: - lineno = -1 - while index < len(tokens): - token = tokens[index] - assert isinstance(token, TokenObject) # rtyper info + check - if token.get_value() == 'for': - index += 1 # skip 'for' - ass_node = to_lvalue(tokens[index], consts.OP_ASSIGN) - index += 2 # skip 'in' - iterable = tokens[index] - index += 1 - while index < len(tokens): - token = tokens[index] - assert isinstance(token, TokenObject) # rtyper info - if token.get_value() == 'if': - ifs.append(ast.GenExprIf(tokens[index+1], token.lineno)) - index += 2 - else: - break - genexpr_fors.append(ast.GenExprFor(ass_node, iterable, ifs, lineno)) - ifs = [] - else: - raise SyntaxError('invalid syntax', - token.lineno, token.col) - return genexpr_fors - - -def get_docstring(builder,stmt): - """parses a Stmt node. - - If a docstring if found, the Discard node is **removed** - from and the docstring is returned. - - If no docstring is found, is left unchanged - and None is returned - """ - if not isinstance(stmt, ast.Stmt): - return None - doc = builder.wrap_none() - if len(stmt.nodes): - first_child = stmt.nodes[0] - if isinstance(first_child, ast.Discard): - expr = first_child.expr - if builder.is_string_const(expr): - # This *is* a docstring, remove it from stmt list - assert isinstance(expr, ast.Const) - del stmt.nodes[0] - doc = expr.value - return doc - - -def to_lvalue(ast_node, flags): - lineno = ast_node.lineno - if isinstance( ast_node, ast.Name ): - return ast.AssName(ast_node.varname, flags, lineno) - # return ast.AssName(ast_node.name, flags) - elif isinstance(ast_node, ast.Tuple): - nodes = [] - # FIXME: should ast_node.getChildren() but it's not annotable - # because of flatten() - for node in ast_node.nodes: - nodes.append(to_lvalue(node, flags)) - return ast.AssTuple(nodes, lineno) - elif isinstance(ast_node, ast.List): - nodes = [] - # FIXME: should ast_node.getChildren() but it's not annotable - # because of flatten() - for node in ast_node.nodes: - nodes.append(to_lvalue(node, flags)) - return ast.AssList(nodes, lineno) - elif isinstance(ast_node, ast.Getattr): - expr = ast_node.expr - assert isinstance(ast_node, ast.Getattr) - attrname = ast_node.attrname - return ast.AssAttr(expr, attrname, flags, lineno) - elif isinstance(ast_node, ast.Subscript): - ast_node.flags = flags - return ast_node - elif isinstance(ast_node, ast.Slice): - ast_node.flags = flags - return ast_node - else: - if isinstance(ast_node, ast.GenExpr): - raise SyntaxError("assign to generator expression not possible", - lineno, 0, '') - elif isinstance(ast_node, ast.ListComp): - raise SyntaxError("can't assign to list comprehension", - lineno, 0, '') - elif isinstance(ast_node, ast.CallFunc): - if flags == consts.OP_DELETE: - raise SyntaxError("can't delete function call", - lineno, 0, '') - else: - raise SyntaxError("can't assign to function call", - lineno, 0, '') - else: - raise SyntaxError("can't assign to non-lvalue", - lineno, 0, '') - -def is_augassign( ast_node ): - if ( isinstance( ast_node, ast.Name ) or - isinstance( ast_node, ast.Slice ) or - isinstance( ast_node, ast.Subscript ) or - isinstance( ast_node, ast.Getattr ) ): - return True - return False - -def get_atoms(builder, nb): - atoms = [] - i = nb - while i>0: - obj = builder.pop() - if isinstance(obj, BaseRuleObject): - i += obj.count - else: - atoms.append( obj ) - i -= 1 - atoms.reverse() - return atoms - -#def eval_string(value): -# """temporary implementation -# -# FIXME: need to be finished (check compile.c (parsestr) and -# stringobject.c (PyString_DecodeEscape()) for complete implementation) -# """ -# # return eval(value) -# if len(value) == 2: -# return '' -# result = '' -# length = len(value) -# quotetype = value[0] -# index = 1 -# while index < length and value[index] == quotetype: -# index += 1 -# if index == 6: -# # empty strings like """""" or '''''' -# return '' -# # XXX: is it RPYTHON to do this value[index:-index] -# chars = [char for char in value[index:len(value)-index]] -# result = ''.join(chars) -# result = result.replace('\\\\', '\\') -# d = {'\\b' : '\b', '\\f' : '\f', '\\t' : '\t', '\\n' : '\n', -# '\\r' : '\r', '\\v' : '\v', '\\a' : '\a', -# } -# for escaped, value in d.items(): -# result = result.replace(escaped, value) -# return result - - -## misc utilities, especially for power: rule -def reduce_callfunc(obj, arglist): - """generic factory for CallFunc nodes""" - assert isinstance(arglist, ArglistObject) - return ast.CallFunc(obj, arglist.arguments, - arglist.stararg, arglist.dstararg, arglist.lineno) - -def reduce_subscript(obj, subscript): - """generic factory for Subscript nodes""" - assert isinstance(subscript, SubscriptObject) - return ast.Subscript(obj, consts.OP_APPLY, subscript.value, subscript.lineno) - -def reduce_slice(obj, sliceobj): - """generic factory for Slice nodes""" - assert isinstance(sliceobj, SlicelistObject) - if sliceobj.fake_rulename == 'slice': - start = sliceobj.value[0] - end = sliceobj.value[1] - return ast.Slice(obj, consts.OP_APPLY, start, end, sliceobj.lineno) - else: - return ast.Subscript(obj, consts.OP_APPLY, ast.Sliceobj(sliceobj.value, - sliceobj.lineno), sliceobj.lineno) - -def parse_attraccess(tokens): - """parses token list like ['a', '.', 'b', '.', 'c', ...] - - and returns an ast node : ast.Getattr(Getattr(Name('a'), 'b'), 'c' ...) - """ - token = tokens[0] - # XXX HACK for when parse_attraccess is called from build_decorator - if isinstance(token, TokenObject): - val = token.get_value() - result = ast.Name(val, token.lineno) - else: - result = token - index = 1 - while index < len(tokens): - token = tokens[index] - if isinstance(token, TokenObject) and token.name == tok.DOT: - index += 1 - token = tokens[index] - assert isinstance(token, TokenObject) - result = ast.Getattr(result, token.get_value(), token.lineno) - elif isinstance(token, ArglistObject): - result = reduce_callfunc(result, token) - elif isinstance(token, SubscriptObject): - result = reduce_subscript(result, token) - elif isinstance(token, SlicelistObject): - result = reduce_slice(result, token) - else: - assert False, "Don't know how to handle index %s of %s" % (index, len(tokens)) - index += 1 - return result - +from asthelper import * ## building functions helpers ## -------------------------- @@ -547,31 +46,31 @@ top = atoms[0] if isinstance(top, TokenObject): # assert isinstance(top, TokenObject) # rtyper - if top.name == tok.LPAR: + if top.name == builder.parser.LPAR: if len(atoms) == 2: builder.push(ast.Tuple([], top.lineno)) else: builder.push( atoms[1] ) - elif top.name == tok.LSQB: + elif top.name == builder.parser.LSQB: if len(atoms) == 2: builder.push(ast.List([], top.lineno)) else: list_node = atoms[1] list_node.lineno = top.lineno builder.push(list_node) - elif top.name == tok.LBRACE: + elif top.name == builder.parser.LBRACE: items = [] for index in range(1, len(atoms)-1, 4): # a : b , c : d # ^ +1 +2 +3 +4 items.append((atoms[index], atoms[index+2])) builder.push(ast.Dict(items, top.lineno)) - elif top.name == tok.NAME: + elif top.name == builder.parser.NAME: val = top.get_value() builder.push( ast.Name(val, top.lineno) ) - elif top.name == tok.NUMBER: + elif top.name == builder.parser.NUMBER: builder.push(ast.Const(builder.eval_number(top.get_value()), top.lineno)) - elif top.name == tok.STRING: + elif top.name == builder.parser.STRING: # need to concatenate strings in atoms s = '' if len(atoms) == 1: @@ -587,7 +86,7 @@ accum.append(parsestr(builder.space, builder.source_encoding, token.get_value())) w_s = space.call_method(empty, 'join', space.newlist(accum)) builder.push(ast.Const(w_s, top.lineno)) - elif top.name == tok.BACKQUOTE: + elif top.name == builder.parser.BACKQUOTE: builder.push(ast.Backquote(atoms[1], atoms[1].lineno)) else: raise SyntaxError("unexpected tokens", top.lineno, top.col) @@ -608,11 +107,11 @@ else: lineno = atoms[0].lineno token = atoms[-2] - if isinstance(token, TokenObject) and token.name == tok.DOUBLESTAR: - obj = parse_attraccess(slicecut(atoms, 0, -2)) + if isinstance(token, TokenObject) and token.name == builder.parser.DOUBLESTAR: + obj = parse_attraccess(slicecut(atoms, 0, -2), builder) builder.push(ast.Power( obj, atoms[-1], lineno)) else: - obj = parse_attraccess(atoms) + obj = parse_attraccess(atoms, builder) builder.push(obj) def build_factor(builder, nb): @@ -623,11 +122,11 @@ token = atoms[0] lineno = token.lineno if isinstance(token, TokenObject): - if token.name == tok.PLUS: + if token.name == builder.parser.PLUS: builder.push( ast.UnaryAdd( atoms[1], lineno) ) - if token.name == tok.MINUS: + if token.name == builder.parser.MINUS: builder.push( ast.UnarySub( atoms[1], lineno) ) - if token.name == tok.TILDE: + if token.name == builder.parser.TILDE: builder.push( ast.Invert( atoms[1], lineno) ) def build_term(builder, nb): @@ -638,13 +137,13 @@ right = atoms[i] op_node = atoms[i-1] assert isinstance(op_node, TokenObject) - if op_node.name == tok.STAR: + if op_node.name == builder.parser.STAR: left = ast.Mul( left, right, left.lineno ) - elif op_node.name == tok.SLASH: + elif op_node.name == builder.parser.SLASH: left = ast.Div( left, right, left.lineno ) - elif op_node.name == tok.PERCENT: + elif op_node.name == builder.parser.PERCENT: left = ast.Mod( left, right, left.lineno ) - elif op_node.name == tok.DOUBLESLASH: + elif op_node.name == builder.parser.DOUBLESLASH: left = ast.FloorDiv( left, right, left.lineno ) else: token = atoms[i-1] @@ -659,9 +158,9 @@ right = atoms[i] op_node = atoms[i-1] assert isinstance(op_node, TokenObject) - if op_node.name == tok.PLUS: + if op_node.name == builder.parser.PLUS: left = ast.Add( left, right, left.lineno) - elif op_node.name == tok.MINUS: + elif op_node.name == builder.parser.MINUS: left = ast.Sub( left, right, left.lineno) else: token = atoms[i-1] @@ -677,9 +176,9 @@ right = atoms[i] op_node = atoms[i-1] assert isinstance(op_node, TokenObject) - if op_node.name == tok.LEFTSHIFT: + if op_node.name == builder.parser.LEFTSHIFT: left = ast.LeftShift( left, right, lineno ) - elif op_node.name == tok.RIGHTSHIFT: + elif op_node.name == builder.parser.RIGHTSHIFT: left = ast.RightShift( left, right, lineno ) else: token = atoms[i-1] @@ -728,7 +227,7 @@ # 'is', 'is not', 'not' or 'not in' => tok.get_value() token = atoms[i] assert isinstance(token, TokenObject) - op_name = tok.tok_rvalues.get(token.name, token.get_value()) + op_name = builder.parser.tok_rvalues.get(token.name, token.get_value()) ops.append((op_name, atoms[i+1])) builder.push(ast.Compare(atoms[0], ops, atoms[0].lineno)) @@ -756,9 +255,9 @@ lineno = token.lineno assert isinstance(token, TokenObject) if token.get_value() == 'not': - builder.push(TokenObject(tok.NAME, 'not in', lineno)) + builder.push(TokenObject(builder.parser.NAME, 'not in', lineno, builder.parser)) else: - builder.push(TokenObject(tok.NAME, 'is not', lineno)) + builder.push(TokenObject(builder.parser.NAME, 'is not', lineno, builder.parser)) else: assert False, "TODO" # uh ? @@ -810,7 +309,7 @@ return op = atoms[1] assert isinstance(op, TokenObject) - if op.name == tok.EQUAL: + if op.name == builder.parser.EQUAL: nodes = [] for i in range(0,l-2,2): lvalue = to_lvalue(atoms[i], consts.OP_ASSIGN) @@ -844,7 +343,7 @@ lineno = -1 for n in range(0,l,2): node = atoms[n] - if isinstance(node, TokenObject) and node.name == tok.NEWLINE: + if isinstance(node, TokenObject) and node.name == builder.parser.NEWLINE: nodes.append(ast.Discard(ast.Const(builder.wrap_none()), node.lineno)) else: nodes.append(node) @@ -870,10 +369,10 @@ for node in atoms: if isinstance(node, ast.Stmt): stmts.extend(node.nodes) - elif isinstance(node, TokenObject) and node.name == tok.ENDMARKER: + elif isinstance(node, TokenObject) and node.name == builder.parser.ENDMARKER: # XXX Can't we just remove the last element of the list ? break - elif isinstance(node, TokenObject) and node.name == tok.NEWLINE: + elif isinstance(node, TokenObject) and node.name == builder.parser.NEWLINE: continue else: stmts.append(node) @@ -893,7 +392,7 @@ l = len(atoms) if l == 1 or l==2: atom0 = atoms[0] - if isinstance(atom0, TokenObject) and atom0.name == tok.NEWLINE: + if isinstance(atom0, TokenObject) and atom0.name == builder.parser.NEWLINE: atom0 = ast.Pass(atom0.lineno) elif not isinstance(atom0, ast.Stmt): atom0 = ast.Stmt([atom0], atom0.lineno) @@ -913,7 +412,7 @@ return items = [] token = atoms[1] - if isinstance(token, TokenObject) and token.name == tok.COMMA: + if isinstance(token, TokenObject) and token.name == builder.parser.COMMA: for i in range(0, l, 2): # this is atoms not 1 items.append(atoms[i]) else: @@ -943,7 +442,7 @@ atoms = get_atoms(builder, nb) lineno = atoms[0].lineno code = atoms[-1] - names, defaults, flags = parse_arglist(slicecut(atoms, 1, -2)) + names, defaults, flags = parse_arglist(slicecut(atoms, 1, -2), builder) builder.push(ast.Lambda(names, defaults, flags, code, lineno)) @@ -953,13 +452,13 @@ atoms = get_atoms(builder, nb) first_token = atoms[0] # Case 1 : '(' ... - if isinstance(first_token, TokenObject) and first_token.name == tok.LPAR: - if len(atoms) == 2: # and atoms[1].token == tok.RPAR: + if isinstance(first_token, TokenObject) and first_token.name == builder.parser.LPAR: + if len(atoms) == 2: # and atoms[1].token == builder.parser.RPAR: builder.push(ArglistObject([], None, None, first_token.lineno)) elif len(atoms) == 3: # '(' Arglist ')' # push arglist on the stack builder.push(atoms[1]) - elif isinstance(first_token, TokenObject) and first_token.name == tok.LSQB: + elif isinstance(first_token, TokenObject) and first_token.name == builder.parser.LSQB: if len(atoms) == 3 and isinstance(atoms[1], SlicelistObject): builder.push(atoms[1]) else: @@ -1003,7 +502,7 @@ [argument ','] ) """ atoms = get_atoms(builder, nb) - arguments, stararg, dstararg = parse_argument(atoms) + arguments, stararg, dstararg = parse_argument(atoms, builder) if atoms: lineno = atoms[0].lineno else: @@ -1017,11 +516,11 @@ atoms = get_atoms(builder, nb) token = atoms[0] lineno = token.lineno - if isinstance(token, TokenObject) and token.name == tok.DOT: + if isinstance(token, TokenObject) and token.name == builder.parser.DOT: # Ellipsis: builder.push(ast.Ellipsis(lineno)) elif len(atoms) == 1: - if isinstance(token, TokenObject) and token.name == tok.COLON: + if isinstance(token, TokenObject) and token.name == builder.parser.COLON: sliceinfos = [None, None, None] builder.push(SlicelistObject('slice', sliceinfos, lineno)) else: @@ -1031,7 +530,7 @@ sliceinfos = [None, None, None] infosindex = 0 for token in atoms: - if isinstance(token, TokenObject) and token.name == tok.COLON: + if isinstance(token, TokenObject) and token.name == builder.parser.COLON: infosindex += 1 else: sliceinfos[infosindex] = token @@ -1056,7 +555,7 @@ if token.get_value() == 'for': # list comp expr = atoms[0] - list_for = parse_listcomp(atoms[1:]) + list_for = parse_listcomp(atoms[1:], builder) builder.push(ast.ListComp(expr, list_for, lineno)) return # regular list building (like in [1, 2, 3,]) @@ -1079,12 +578,12 @@ # remove '@', '(' and ')' from atoms and use parse_attraccess for token in atoms[1:]: if isinstance(token, TokenObject) and \ - token.name in (tok.LPAR, tok.RPAR, tok.NEWLINE): + token.name in (builder.parser.LPAR, builder.parser.RPAR, builder.parser.NEWLINE): # skip those ones continue else: nodes.append(token) - obj = parse_attraccess(nodes) + obj = parse_attraccess(nodes, builder) builder.push(obj) def build_funcdef(builder, nb): @@ -1113,7 +612,7 @@ arglist = [] index = 3 arglist = slicecut(atoms, 3, -3) - names, default, flags = parse_arglist(arglist) + names, default, flags = parse_arglist(arglist, builder) funcname_token = atoms[1] assert isinstance(funcname_token, TokenObject) funcname = funcname_token.get_value() @@ -1294,7 +793,7 @@ while index < l: as_name = None # dotted name (a.b.c) - incr, name = parse_dotted_names(atoms[index:]) + incr, name = parse_dotted_names(atoms[index:], builder) index += incr # 'as' value if index < l: @@ -1311,11 +810,11 @@ while index 1: token = atoms[1] - if isinstance(token, TokenObject) and token.name == tok.RIGHTSHIFT: + if isinstance(token, TokenObject) and token.name == builder.parser.RIGHTSHIFT: dest = atoms[2] # skip following comma start = 4 for index in range(start, l, 2): items.append(atoms[index]) last_token = atoms[-1] - if isinstance(last_token, TokenObject) and last_token.name == tok.COMMA: + if isinstance(last_token, TokenObject) and last_token.name == builder.parser.COMMA: builder.push(ast.Print(items, dest, atoms[0].lineno)) else: builder.push(ast.Printnl(items, dest, atoms[0].lineno)) @@ -1465,8 +964,8 @@ """ atoms = get_atoms(builder, nb) - l = len(atoms) handlers = [] + l = len(atoms) else_ = None body = atoms[2] token = atoms[3] @@ -1547,129 +1046,9 @@ } # Build two almost identical ASTRULES dictionaries -ASTRULES = dict([(sym[key], value) for (key, value) in - ASTRULES_Template.iteritems()]) -del ASTRULES_Template - -## Stack elements definitions ################################### - -class BaseRuleObject(ast.Node): - """Base class for unnamed rules""" - def __init__(self, count, lineno): - self.count = count - self.lineno = lineno # src.getline() - self.col = 0 # src.getcol() - - -class RuleObject(BaseRuleObject): - """A simple object used to wrap a rule or token""" - def __init__(self, name, count, lineno): - BaseRuleObject.__init__(self, count, lineno) - self.rulename = name - - def __str__(self): - return "" % ( rsym[self.rulename], self.count) - - def __repr__(self): - return "" % ( rsym[self.rulename], self.count) - - -class TempRuleObject(BaseRuleObject): - """used to keep track of how many items get_atom() should pop""" - def __init__(self, name, count, lineno): - BaseRuleObject.__init__(self, count, lineno) - self.temp_rulename = name - - def __str__(self): - return "" % (self.temp_rulename, self.count) - - def __repr__(self): - return "" % (self.temp_rulename, self.count) - - -class TokenObject(ast.Node): - """A simple object used to wrap a rule or token""" - def __init__(self, name, value, lineno): - self.name = name - self.value = value - self.count = 0 - # self.line = 0 # src.getline() - self.col = 0 # src.getcol() - self.lineno = lineno - - def get_name(self): - return tok.tok_rvalues.get(self.name, - tok.tok_name.get(self.name, str(self.name))) - - def get_value(self): - value = self.value - if value is None: - value = '' - return value - - def __str__(self): - return "" % (self.get_name(), self.value) - - def __repr__(self): - return "" % (self.get_name(), self.value) - - -class ObjectAccessor(ast.Node): - """base class for ArglistObject, SubscriptObject and SlicelistObject - - FIXME: think about a more appropriate name - """ - -class ArglistObject(ObjectAccessor): - """helper class to build function's arg list - """ - def __init__(self, arguments, stararg, dstararg, lineno): - self.fake_rulename = 'arglist' - self.arguments = arguments - self.stararg = stararg - self.dstararg = dstararg - self.lineno = lineno - - def __str__(self): - return "" % self.value - - def __repr__(self): - return "" % self.value - -class SubscriptObject(ObjectAccessor): - """helper class to build subscript list - - self.value represents the __getitem__ argument - """ - def __init__(self, name, value, lineno): - self.fake_rulename = name - self.value = value - self.lineno = lineno - - def __str__(self): - return "" % self.value - - def __repr__(self): - return "" % self.value - -class SlicelistObject(ObjectAccessor): - """helper class to build slice objects - - self.value is a list [start, end, step] - self.fake_rulename can either be 'slice' or 'sliceobj' depending - on if a step is specfied or not (see Python's AST - for more information on that) - """ - def __init__(self, name, value, lineno): - self.fake_rulename = name - self.value = value - self.lineno = lineno - - def __str__(self): - return "" % self.value - - def __repr__(self): - return "" % self.value +#ASTRULES = dict([(sym[key], value) for (key, value) in +# ASTRULES_Template.iteritems()]) +#del ASTRULES_Template class AstBuilderContext(AbstractContext): @@ -1678,17 +1057,21 @@ #self.rule_stack = list(rule_stack) self.d = len(rule_stack) -class AstBuilder(BaseGrammarBuilder): +from pypy.interpreter.baseobjspace import Wrappable +class AstBuilder(Wrappable, BaseGrammarBuilder): """A builder that directly produce the AST""" def __init__(self, parser=None, debug=0, space=None): if parser is None: + from pythonparse import PYTHON_PARSER parser = pythonparse.PYTHON_PARSER BaseGrammarBuilder.__init__(self, parser, debug) self.rule_stack = [] self.space = space self.source_encoding = None self.with_enabled = False + self.build_rules = dict(ASTRULES_Template) + def enable_with(self): if self.with_enabled: @@ -1717,17 +1100,25 @@ ## pass def push_tok(self, name, value, src ): - self.push( TokenObject( name, value, src._token_lnum ) ) + self.push( TokenObject( name, value, src._token_lnum, self.parser ) ) def push_rule(self, name, count, src ): - self.push( RuleObject( name, count, src._token_lnum ) ) + self.push( RuleObject( name, count, src._token_lnum, self.parser ) ) def alternative( self, rule, source ): # Do nothing, keep rule on top of the stack ## rule_stack = self.rule_stack[:] if rule.is_root(): - builder_func = ASTRULES.get(rule.codename, None) - if builder_func: + rulename = self.parser.sym_name[rule.codename] + # builder_func = ASTRULES.get(rule.codename, None) + builder_func = self.build_rules.get(rulename, None) + # user defined (applevel) function + if isinstance(builder_func, Function): + w_items = self.space.newlist( [self.space.wrap( it ) for it in get_atoms(self, 1)] ) + w_astnode = self.space.call_function(builder_func, w_items) + astnode = self.space.interp_w(ast.Node, w_astnode, can_be_None=False) + self.push(astnode) + elif builder_func: builder_func(self, 1) else: self.push_rule(rule.codename, 1, source) @@ -1739,8 +1130,15 @@ """ """ ## rule_stack = self.rule_stack[:] if rule.is_root(): - builder_func = ASTRULES.get(rule.codename, None) - if builder_func: + rulename = self.parser.sym_name[rule.codename] + # builder_func = ASTRULES.get(rule.codename, None) + builder_func = self.build_rules.get(rulename, None) + if isinstance(builder_func, Function): + w_items = self.space.newlist( [self.space.wrap( it ) for it in get_atoms(self, elts_number)] ) + w_astnode = self.space.call_function(builder_func, w_items) + astnode = self.space.interp_w(ast.Node, w_astnode, can_be_None=False) + self.push(astnode) + elif builder_func: builder_func(self, elts_number) else: self.push_rule(rule.codename, elts_number, source) Added: pypy/branch/ast-experiments/pypy/interpreter/pyparser/asthelper.py ============================================================================== --- (empty file) +++ pypy/branch/ast-experiments/pypy/interpreter/pyparser/asthelper.py Thu Dec 21 16:13:54 2006 @@ -0,0 +1,635 @@ +from pypy.interpreter.typedef import TypeDef, GetSetProperty, interp_attrproperty +from pypy.interpreter.astcompiler import ast, consts +from pypy.interpreter.pyparser.error import SyntaxError + + +### Parsing utilites ################################################# +def parse_except_clause(tokens): + """parses 'except' [test [',' test]] ':' suite + and returns a 4-tuple : (tokens_read, expr1, expr2, except_body) + """ + lineno = tokens[0].lineno + clause_length = 1 + # Read until end of except clause (bound by following 'else', + # or 'except' or end of tokens) + while clause_length < len(tokens): + token = tokens[clause_length] + if isinstance(token, TokenObject) and \ + (token.get_value() == 'except' or token.get_value() == 'else'): + break + clause_length += 1 + if clause_length == 3: + # case 'except: body' + return (3, None, None, tokens[2]) + elif clause_length == 4: + # case 'except Exception: body': + return (4, tokens[1], None, tokens[3]) + else: + # case 'except Exception, exc: body' + return (6, tokens[1], to_lvalue(tokens[3], consts.OP_ASSIGN), tokens[5]) + + +def parse_dotted_names(tokens, builder): + """parses NAME('.' NAME)* and returns full dotted name + + this function doesn't assume that the list ends after the + last 'NAME' element + """ + first = tokens[0] + assert isinstance(first, TokenObject) + name = first.get_value() + l = len(tokens) + index = 1 + for index in range(1, l, 2): + token = tokens[index] + assert isinstance(token, TokenObject) + if token.name != builder.parser.DOT: + break + token = tokens[index+1] + assert isinstance(token, TokenObject) + name += '.' + value = token.get_value() + name += value + return (index, name) + +def parse_argument(tokens, builder): + """parses function call arguments""" + l = len(tokens) + index = 0 + arguments = [] + last_token = None + building_kw = False + kw_built = False + stararg_token = None + dstararg_token = None + while index < l: + cur_token = tokens[index] + if not isinstance(cur_token, TokenObject): + index += 1 + if not building_kw: + arguments.append(cur_token) + else: + last_token = arguments.pop() + assert isinstance(last_token, ast.Name) # used by rtyper + arguments.append(ast.Keyword(last_token.varname, cur_token, last_token.lineno)) + building_kw = False + kw_built = True + continue + elif cur_token.name == builder.parser.COMMA: + index += 1 + continue + elif cur_token.name == builder.parser.EQUAL: + index += 1 + building_kw = True + continue + elif cur_token.name == builder.parser.STAR or cur_token.name == builder.parser.DOUBLESTAR: + index += 1 + if cur_token.name == builder.parser.STAR: + stararg_token = tokens[index] + index += 1 + if index >= l: + break + index += 2 # Skip COMMA and DOUBLESTAR + dstararg_token = tokens[index] + break + elif cur_token.get_value() == 'for': + if len(arguments) != 1: + raise SyntaxError("invalid syntax", cur_token.lineno, + cur_token.col) + expr = arguments[0] + genexpr_for = parse_genexpr_for(tokens[index:]) + genexpr_for[0].is_outmost = True + gexp = ast.GenExpr(ast.GenExprInner(expr, genexpr_for, expr.lineno), expr.lineno) + arguments[0] = gexp + break + return arguments, stararg_token, dstararg_token + + +def parse_fpdef(tokens, index, builder): + """fpdef: fpdef: NAME | '(' fplist ')' + fplist: fpdef (',' fpdef)* [','] + + This intend to be a RPYTHON compliant implementation of _parse_fpdef, + but it can't work with the default compiler. + We switched to use astcompiler module now + """ + nodes = [] + comma = False + while True: + token = tokens[index] + index += 1 + assert isinstance(token, TokenObject) + if token.name == builder.parser.LPAR: # nested item + index, node = parse_fpdef(tokens, index, builder) + elif token.name == builder.parser.RPAR: # end of current nesting + break + else: # name + val = token.get_value() + node = ast.AssName(val, consts.OP_ASSIGN, token.lineno) + nodes.append(node) + + token = tokens[index] + index += 1 + assert isinstance(token, TokenObject) + if token.name == builder.parser.COMMA: + comma = True + else: + assert token.name == builder.parser.RPAR + break + if len(nodes) == 1 and not comma: + node = nodes[0] + else: + node = ast.AssTuple(nodes, token.lineno) + return index, node + +def parse_arglist(tokens, builder): + """returns names, defaults, flags""" + l = len(tokens) + index = 0 + defaults = [] + names = [] + flags = 0 + first_with_default = -1 + while index < l: + cur_token = tokens[index] + index += 1 + if not isinstance(cur_token, TokenObject): + # XXX: think of another way to write this test + defaults.append(cur_token) + if first_with_default == -1: + first_with_default = len(names) - 1 + elif cur_token.name == builder.parser.COMMA: + # We could skip test COMMA by incrementing index cleverly + # but we might do some experiment on the grammar at some point + continue + elif cur_token.name == builder.parser.LPAR: + index, node = parse_fpdef(tokens, index, builder) + names.append(node) + elif cur_token.name == builder.parser.STAR or cur_token.name == builder.parser.DOUBLESTAR: + if cur_token.name == builder.parser.STAR: + cur_token = tokens[index] + assert isinstance(cur_token, TokenObject) + index += 1 + if cur_token.name == builder.parser.NAME: + val = cur_token.get_value() + names.append( ast.AssName( val, consts.OP_ASSIGN ) ) + flags |= consts.CO_VARARGS + index += 1 + if index >= l: + break + else: + # still more tokens to read + cur_token = tokens[index] + index += 1 + else: + raise SyntaxError("incomplete varags", cur_token.lineno, + cur_token.col) + assert isinstance(cur_token, TokenObject) + if cur_token.name != builder.parser.DOUBLESTAR: + raise SyntaxError("Unexpected token", cur_token.lineno, + cur_token.col) + cur_token = tokens[index] + index += 1 + assert isinstance(cur_token, TokenObject) + if cur_token.name == builder.parser.NAME: + val = cur_token.get_value() + names.append( ast.AssName( val, consts.OP_ASSIGN ) ) + flags |= consts.CO_VARKEYWORDS + index += 1 + else: + raise SyntaxError("incomplete varags", cur_token.lineno, + cur_token.col) + if index < l: + token = tokens[index] + raise SyntaxError("unexpected token" , token.lineno, + token.col) + elif cur_token.name == builder.parser.NAME: + val = cur_token.get_value() + names.append( ast.AssName( val, consts.OP_ASSIGN ) ) + + if first_with_default != -1: + num_expected_with_default = len(names) - first_with_default + if flags & consts.CO_VARKEYWORDS: + num_expected_with_default -= 1 + if flags & consts.CO_VARARGS: + num_expected_with_default -= 1 + if len(defaults) != num_expected_with_default: + raise SyntaxError('non-default argument follows default argument', + tokens[0].lineno, tokens[0].col) + return names, defaults, flags + + +def parse_listcomp(tokens, builder): + """parses 'for j in k for i in j if i %2 == 0' and returns + a GenExprFor instance + XXX: refactor with listmaker ? + """ + list_fors = [] + ifs = [] + index = 0 + if tokens: + lineno = tokens[0].lineno + else: + lineno = -1 + while index < len(tokens): + token = tokens[index] + assert isinstance(token, TokenObject) # rtyper info + check + if token.get_value() == 'for': + index += 1 # skip 'for' + ass_node = to_lvalue(tokens[index], consts.OP_ASSIGN) + index += 2 # skip 'in' + iterables = [tokens[index]] + index += 1 + while index < len(tokens): + tok2 = tokens[index] + if not isinstance(tok2, TokenObject): + break + if tok2.name != builder.parser.COMMA: + break + iterables.append(tokens[index+1]) + index += 2 + if len(iterables) == 1: + iterable = iterables[0] + else: + iterable = ast.Tuple(iterables, token.lineno) + while index < len(tokens): + token = tokens[index] + assert isinstance(token, TokenObject) # rtyper info + if token.get_value() == 'if': + ifs.append(ast.ListCompIf(tokens[index+1], token.lineno)) + index += 2 + else: + break + list_fors.append(ast.ListCompFor(ass_node, iterable, ifs, lineno)) + ifs = [] + else: + assert False, 'Unexpected token: expecting for in listcomp' + # + # Original implementation: + # + # if tokens[index].get_value() == 'for': + # index += 1 # skip 'for' + # ass_node = to_lvalue(tokens[index], consts.OP_ASSIGN) + # index += 2 # skip 'in' + # iterable = tokens[index] + # index += 1 + # while index < len(tokens) and tokens[index].get_value() == 'if': + # ifs.append(ast.ListCompIf(tokens[index+1])) + # index += 2 + # list_fors.append(ast.ListCompFor(ass_node, iterable, ifs)) + # ifs = [] + # else: + # raise ValueError('Unexpected token: %s' % tokens[index]) + return list_fors + + +def parse_genexpr_for(tokens): + """parses 'for j in k for i in j if i %2 == 0' and returns + a GenExprFor instance + XXX: if RPYTHON supports to pass a class object to a function, + we could refactor parse_listcomp and parse_genexpr_for, + and call : + - parse_listcomp(tokens, forclass=ast.GenExprFor, ifclass=...) + or: + - parse_listcomp(tokens, forclass=ast.ListCompFor, ifclass=...) + """ + genexpr_fors = [] + ifs = [] + index = 0 + if tokens: + lineno = tokens[0].lineno + else: + lineno = -1 + while index < len(tokens): + token = tokens[index] + assert isinstance(token, TokenObject) # rtyper info + check + if token.get_value() == 'for': + index += 1 # skip 'for' + ass_node = to_lvalue(tokens[index], consts.OP_ASSIGN) + index += 2 # skip 'in' + iterable = tokens[index] + index += 1 + while index < len(tokens): + token = tokens[index] + assert isinstance(token, TokenObject) # rtyper info + if token.get_value() == 'if': + ifs.append(ast.GenExprIf(tokens[index+1], token.lineno)) + index += 2 + else: + break + genexpr_fors.append(ast.GenExprFor(ass_node, iterable, ifs, lineno)) + ifs = [] + else: + raise SyntaxError('invalid syntax', + token.lineno, token.col) + return genexpr_fors + +def get_docstring(builder,stmt): + """parses a Stmt node. + + If a docstring if found, the Discard node is **removed** + from and the docstring is returned. + + If no docstring is found, is left unchanged + and None is returned + """ + if not isinstance(stmt, ast.Stmt): + return None + doc = builder.wrap_none() + if len(stmt.nodes): + first_child = stmt.nodes[0] + if isinstance(first_child, ast.Discard): + expr = first_child.expr + if builder.is_string_const(expr): + # This *is* a docstring, remove it from stmt list + assert isinstance(expr, ast.Const) + del stmt.nodes[0] + doc = expr.value + return doc + + +def to_lvalue(ast_node, flags): + lineno = ast_node.lineno + if isinstance( ast_node, ast.Name ): + return ast.AssName(ast_node.varname, flags, lineno) + # return ast.AssName(ast_node.name, flags) + elif isinstance(ast_node, ast.Tuple): + nodes = [] + # FIXME: should ast_node.getChildren() but it's not annotable + # because of flatten() + for node in ast_node.nodes: + nodes.append(to_lvalue(node, flags)) + return ast.AssTuple(nodes, lineno) + elif isinstance(ast_node, ast.List): + nodes = [] + # FIXME: should ast_node.getChildren() but it's not annotable + # because of flatten() + for node in ast_node.nodes: + nodes.append(to_lvalue(node, flags)) + return ast.AssList(nodes, lineno) + elif isinstance(ast_node, ast.Getattr): + expr = ast_node.expr + assert isinstance(ast_node, ast.Getattr) + attrname = ast_node.attrname + return ast.AssAttr(expr, attrname, flags, lineno) + elif isinstance(ast_node, ast.Subscript): + ast_node.flags = flags + return ast_node + elif isinstance(ast_node, ast.Slice): + ast_node.flags = flags + return ast_node + else: + if isinstance(ast_node, ast.GenExpr): + raise SyntaxError("assign to generator expression not possible", + lineno, 0, '') + elif isinstance(ast_node, ast.ListComp): + raise SyntaxError("can't assign to list comprehension", + lineno, 0, '') + elif isinstance(ast_node, ast.CallFunc): + if flags == consts.OP_DELETE: + raise SyntaxError("can't delete function call", + lineno, 0, '') + else: + raise SyntaxError("can't assign to function call", + lineno, 0, '') + else: + raise SyntaxError("can't assign to non-lvalue", + lineno, 0, '') + +def is_augassign( ast_node ): + if ( isinstance( ast_node, ast.Name ) or + isinstance( ast_node, ast.Slice ) or + isinstance( ast_node, ast.Subscript ) or + isinstance( ast_node, ast.Getattr ) ): + return True + return False + +def get_atoms(builder, nb): + atoms = [] + i = nb + while i>0: + obj = builder.pop() + if isinstance(obj, BaseRuleObject): + i += obj.count + else: + atoms.append( obj ) + i -= 1 + atoms.reverse() + return atoms + +#def eval_string(value): +# """temporary implementation +# +# FIXME: need to be finished (check compile.c (parsestr) and +# stringobject.c (PyString_DecodeEscape()) for complete implementation) +# """ +# # return eval(value) +# if len(value) == 2: +# return '' +# result = '' +# length = len(value) +# quotetype = value[0] +# index = 1 +# while index < length and value[index] == quotetype: +# index += 1 +# if index == 6: +# # empty strings like """""" or '''''' +# return '' +# # XXX: is it RPYTHON to do this value[index:-index] +# chars = [char for char in value[index:len(value)-index]] +# result = ''.join(chars) +# result = result.replace('\\\\', '\\') +# d = {'\\b' : '\b', '\\f' : '\f', '\\t' : '\t', '\\n' : '\n', +# '\\r' : '\r', '\\v' : '\v', '\\a' : '\a', +# } +# for escaped, value in d.items(): +# result = result.replace(escaped, value) +# return result + + +## misc utilities, especially for power: rule +def reduce_callfunc(obj, arglist): + """generic factory for CallFunc nodes""" + assert isinstance(arglist, ArglistObject) + return ast.CallFunc(obj, arglist.arguments, + arglist.stararg, arglist.dstararg, arglist.lineno) + +def reduce_subscript(obj, subscript): + """generic factory for Subscript nodes""" + assert isinstance(subscript, SubscriptObject) + return ast.Subscript(obj, consts.OP_APPLY, subscript.value, subscript.lineno) + +def reduce_slice(obj, sliceobj): + """generic factory for Slice nodes""" + assert isinstance(sliceobj, SlicelistObject) + if sliceobj.fake_rulename == 'slice': + start = sliceobj.value[0] + end = sliceobj.value[1] + return ast.Slice(obj, consts.OP_APPLY, start, end, sliceobj.lineno) + else: + return ast.Subscript(obj, consts.OP_APPLY, ast.Sliceobj(sliceobj.value, + sliceobj.lineno), sliceobj.lineno) + +def parse_attraccess(tokens, builder): + """parses token list like ['a', '.', 'b', '.', 'c', ...] + + and returns an ast node : ast.Getattr(Getattr(Name('a'), 'b'), 'c' ...) + """ + token = tokens[0] + # XXX HACK for when parse_attraccess is called from build_decorator + if isinstance(token, TokenObject): + val = token.get_value() + result = ast.Name(val, token.lineno) + else: + result = token + index = 1 + while index < len(tokens): + token = tokens[index] + if isinstance(token, TokenObject) and token.name == builder.parser.DOT: + index += 1 + token = tokens[index] + assert isinstance(token, TokenObject) + result = ast.Getattr(result, token.get_value(), token.lineno) + elif isinstance(token, ArglistObject): + result = reduce_callfunc(result, token) + elif isinstance(token, SubscriptObject): + result = reduce_subscript(result, token) + elif isinstance(token, SlicelistObject): + result = reduce_slice(result, token) + else: + assert False, "Don't know how to handle index %s of %s" % (index, len(tokens)) + index += 1 + return result + + + +## Stack elements definitions ################################### + +class BaseRuleObject(ast.Node): + """Base class for unnamed rules""" + def __init__(self, count, lineno): + self.count = count + self.lineno = lineno # src.getline() + self.col = 0 # src.getcol() + + +class RuleObject(BaseRuleObject): + """A simple object used to wrap a rule or token""" + def __init__(self, name, count, lineno, parser): + BaseRuleObject.__init__(self, count, lineno) + self.rulename = name + self.parser = parser + + def __str__(self): + return "" % ( self.parser.symbol_repr(self.rulename), self.count) + + def __repr__(self): + return "" % ( self.parser.symbol_repr(self.rulename), self.count) + + +class TempRuleObject(BaseRuleObject): + """used to keep track of how many items get_atom() should pop""" + def __init__(self, name, count, lineno): + BaseRuleObject.__init__(self, count, lineno) + self.temp_rulename = name + + def __str__(self): + return "" % (self.temp_rulename, self.count) + + def __repr__(self): + return "" % (self.temp_rulename, self.count) + + +class TokenObject(ast.Node): + """A simple object used to wrap a rule or token""" + def __init__(self, name, value, lineno, parser): + self.name = name + self.value = value + self.count = 0 + # self.line = 0 # src.getline() + self.col = 0 # src.getcol() + self.lineno = lineno + self.parser = parser + + def get_name(self): + tokname = self.parser.tok_name.get(self.name, str(self.name)) + return self.parser.tok_rvalues.get(self.name, tokname) + + def get_value(self): + value = self.value + if value is None: + value = '' + return value + + def descr_fget_value(space, self): + value = self.get_value() + return space.wrap(value) + + def __str__(self): + return "" % (self.get_name(), self.value) + + def __repr__(self): + return "" % (self.get_name(), self.value) + +TokenObject.typedef = TypeDef('BuildToken', + name=interp_attrproperty('name', cls=TokenObject), + lineno=interp_attrproperty('lineno', cls=TokenObject), + value=GetSetProperty(TokenObject.descr_fget_value)) + +class ObjectAccessor(ast.Node): + """base class for ArglistObject, SubscriptObject and SlicelistObject + + FIXME: think about a more appropriate name + """ + +class ArglistObject(ObjectAccessor): + """helper class to build function's arg list + """ + def __init__(self, arguments, stararg, dstararg, lineno): + self.fake_rulename = 'arglist' + self.arguments = arguments + self.stararg = stararg + self.dstararg = dstararg + self.lineno = lineno + + def __str__(self): + return "" % self.value + + def __repr__(self): + return "" % self.value + +class SubscriptObject(ObjectAccessor): + """helper class to build subscript list + + self.value represents the __getitem__ argument + """ + def __init__(self, name, value, lineno): + self.fake_rulename = name + self.value = value + self.lineno = lineno + + def __str__(self): + return "" % self.value + + def __repr__(self): + return "" % self.value + +class SlicelistObject(ObjectAccessor): + """helper class to build slice objects + + self.value is a list [start, end, step] + self.fake_rulename can either be 'slice' or 'sliceobj' depending + on if a step is specfied or not (see Python's AST + for more information on that) + """ + def __init__(self, name, value, lineno): + self.fake_rulename = name + self.value = value + self.lineno = lineno + + def __str__(self): + return "" % self.value + + def __repr__(self): + return "" % self.value + Modified: pypy/branch/ast-experiments/pypy/interpreter/pyparser/grammar.py ============================================================================== --- pypy/branch/ast-experiments/pypy/interpreter/pyparser/grammar.py (original) +++ pypy/branch/ast-experiments/pypy/interpreter/pyparser/grammar.py Thu Dec 21 16:13:54 2006 @@ -362,7 +362,6 @@ pass - class GrammarProxy(GrammarElement): def __init__(self, parser, rule_name, codename=-1 ): GrammarElement.__init__(self, parser, codename ) @@ -395,7 +394,7 @@ returns the object built from the first rules that matches """ if DEBUG > 1: - print "try alt:", self.display(level, builder.symbols ) + print "try alt:", self.display(level) tok = source.peek() # Here we stop at the first match we should # try instead to get the longest alternative @@ -487,10 +486,11 @@ for i in self.args: assert isinstance( i, GrammarElement ) + def _match(self, source, builder, level=0): """matches all of the symbols in order""" if DEBUG > 1: - print "try seq:", self.display(0, builder.symbols ) + print "try seq:", self.display(0) ctx = source.context() bctx = builder.context() for rule in self.args: @@ -574,7 +574,7 @@ represent infinity """ if DEBUG > 1: - print "try kle:", self.display(0,builder.symbols) + print "try kle:", self.display(0) ctx = None bctx = None if self.min: @@ -829,7 +829,7 @@ def Alternative( self, name_id, args ): assert isinstance( name_id, int ) - alt = Alternative( self, name_id, args ) + alt = Alternative( self, name_id, args ) self.all_rules.append( alt ) return alt Modified: pypy/branch/ast-experiments/pypy/interpreter/pyparser/pythonparse.py ============================================================================== --- pypy/branch/ast-experiments/pypy/interpreter/pyparser/pythonparse.py (original) +++ pypy/branch/ast-experiments/pypy/interpreter/pyparser/pythonparse.py Thu Dec 21 16:13:54 2006 @@ -16,8 +16,10 @@ import pypy.interpreter.pyparser.pysymbol as pysymbol import pypy.interpreter.pyparser.pytoken as pytoken import pypy.interpreter.pyparser.ebnfparse as ebnfparse +from pypy.interpreter.pyparser.ebnflexer import GrammarSource +from pypy.interpreter.pyparser.ebnfgrammar import GRAMMAR_GRAMMAR import pypy.interpreter.pyparser.grammar as grammar -from pypy.interpreter.pyparser.pythonutil import build_parser_for_version +from pypy.interpreter.pyparser.pythonutil import build_parser_for_version, build_parser # try: from pypy.interpreter.pyparser import symbol @@ -98,6 +100,7 @@ pytoken.setup_tokens(self) if predefined_symbols: self.load_symbols(predefined_symbols) + self.keywords = [] # XXX (adim): this is trunk's keyword management # self.with_grammar = None @@ -134,7 +137,6 @@ goalnumber = self.symbols[goal] target = self.root_rules[goalnumber] src = Source(self, lines, flags) - if not target.match(src, builder): line, lineno = src.debug() # XXX needs better error messages @@ -142,24 +144,43 @@ # 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, arg in enumerate(rule.args): + 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() -## def eval(self, source, builder=None): -## if builder is None: -## builder = self.builder -## rule = self.root_rules['eval_input'] -## rule.match(source, builder) def get_pyparser_for_version(version): parser = PythonParser(predefined_symbols=symbol.sym_name) return build_parser_for_version(version, parser=parser) - # unfortunately the command line options are not parsed yet debug_print( "Loading grammar %s" % Options.version ) -# PYTHON_PARSER = get_pyparser_for_version(Options.version) -PYTHON_PARSER = get_pyparser_for_version( Options.version ) - +# XXX: remove PYTHON_PARSER +PYTHON_PARSER = get_pyparser_for_version(Options.version) ## XXX BROKEN ## def grammar_rules( space ): Modified: pypy/branch/ast-experiments/pypy/interpreter/pyparser/pythonutil.py ============================================================================== --- pypy/branch/ast-experiments/pypy/interpreter/pyparser/pythonutil.py (original) +++ pypy/branch/ast-experiments/pypy/interpreter/pyparser/pythonutil.py Thu Dec 21 16:13:54 2006 @@ -39,6 +39,7 @@ GRAMMAR_GRAMMAR.root_rules['grammar'].match(source, builder) builder.resolve_rules() parser.build_first_sets() + parser.keywords = builder.keywords return parser Modified: pypy/branch/ast-experiments/pypy/interpreter/pyparser/test/test_astbuilder.py ============================================================================== --- pypy/branch/ast-experiments/pypy/interpreter/pyparser/test/test_astbuilder.py (original) +++ pypy/branch/ast-experiments/pypy/interpreter/pyparser/test/test_astbuilder.py Thu Dec 21 16:13:54 2006 @@ -218,7 +218,7 @@ return ast_from_input(expr, target, t, stable_parser) def source2ast(source, mode, space=FakeSpace()): - builder = AstBuilder(space=space) + builder = AstBuilder(space=space, parser=python_parser) python_parser.parse_source(source, mode, builder) return builder.rule_stack[-1] From adim at codespeak.net Thu Dec 21 16:19:14 2006 From: adim at codespeak.net (adim at codespeak.net) Date: Thu, 21 Dec 2006 16:19:14 +0100 (CET) Subject: [pypy-svn] r35934 - in pypy/branch/ast-experiments/pypy: interpreter module/recparser Message-ID: <20061221151914.7BB2410090@code0.codespeak.net> Author: adim Date: Thu Dec 21 16:19:02 2006 New Revision: 35934 Modified: pypy/branch/ast-experiments/pypy/interpreter/pycompiler.py pypy/branch/ast-experiments/pypy/module/recparser/__init__.py Log: added a hook to modify the grammar rules at applevel Modified: pypy/branch/ast-experiments/pypy/interpreter/pycompiler.py ============================================================================== --- pypy/branch/ast-experiments/pypy/interpreter/pycompiler.py (original) +++ pypy/branch/ast-experiments/pypy/interpreter/pycompiler.py Thu Dec 21 16:19:02 2006 @@ -189,6 +189,7 @@ warnings.warn_explicit = old_warn_explicit + ######## class PythonAstCompiler(PyCodeCompiler): """Uses the stdlib's python implementation of compiler @@ -198,6 +199,15 @@ of incomplete inputs (e.g. we shouldn't re-compile from sracth the whole source after having only added a new '\n') """ + def __init__(self, space): + from pyparser.pythonparse import get_pyparser_for_version + from pypy.tool.option import Options + PyCodeCompiler.__init__(self, space) + self.parser = get_pyparser_for_version(Options.version) + self.additional_rules = {} + + + def compile(self, source, filename, mode, flags): from pyparser.error import SyntaxError from pypy.interpreter import astcompiler @@ -206,14 +216,15 @@ from pypy.interpreter.astcompiler.pycodegen import ExpressionCodeGenerator from pypy.interpreter.astcompiler.ast import Node from pyparser.astbuilder import AstBuilder - from pyparser.pythonparse import PYTHON_PARSER from pypy.interpreter.pycode import PyCode flags |= stdlib___future__.generators.compiler_flag # always on (2.2 compat) space = self.space try: - builder = AstBuilder(space=space) - PYTHON_PARSER.parse_source(source, mode, builder, flags) + builder = AstBuilder(self.parser, space=space) + for rulename, buildfunc in self.additional_rules.iteritems(): + builder.build_rules[rulename] = buildfunc + self.parser.parse_source(source, mode, builder, flags) ast_tree = builder.rule_stack[-1] encoding = builder.source_encoding except SyntaxError, e: @@ -252,3 +263,14 @@ # if not space.get( w_callable ): # 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""" + 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) + space.default_compiler.additional_rules = buildfuncs + space.default_compiler.parser.insert_rule(rule) + Modified: pypy/branch/ast-experiments/pypy/module/recparser/__init__.py ============================================================================== --- pypy/branch/ast-experiments/pypy/module/recparser/__init__.py (original) +++ pypy/branch/ast-experiments/pypy/module/recparser/__init__.py Thu Dec 21 16:19:02 2006 @@ -47,6 +47,7 @@ 'source2ast' : "pyparser.source2ast", 'decode_string_literal': 'pyparser.decode_string_literal', 'install_compiler_hook' : 'pypy.interpreter.pycompiler.install_compiler_hook', + 'insert_grammar_rule' : 'pypy.interpreter.pycompiler.insert_grammar_rule', 'rules' : 'pypy.interpreter.pyparser.pythonparse.grammar_rules', 'parse_grammar' : 'pypy.interpreter.pyparser.pythonparse.parse_grammar', } From afayolle at codespeak.net Thu Dec 21 16:28:36 2006 From: afayolle at codespeak.net (afayolle at codespeak.net) Date: Thu, 21 Dec 2006 16:28:36 +0100 (CET) Subject: [pypy-svn] r35935 - pypy/dist/pypy/tool/build/bin Message-ID: <20061221152836.D803010088@code0.codespeak.net> Author: afayolle Date: Thu Dec 21 16:28:35 2006 New Revision: 35935 Modified: pypy/dist/pypy/tool/build/bin/client Log: fixe NameError Modified: pypy/dist/pypy/tool/build/bin/client ============================================================================== --- pypy/dist/pypy/tool/build/bin/client (original) +++ pypy/dist/pypy/tool/build/bin/client Thu Dec 21 16:28:35 2006 @@ -5,7 +5,7 @@ from pypy.tool.build import outputbuffer def compile(wc, compileinfo): - code = py.code.Source(outputbuffer, """\ + code = """\ import sys import os import traceback @@ -59,9 +59,10 @@ log.close() channel.send(outbuffer.getvalue()) channel.close() - """) + """ gw = PopenGateway() - interpolated = code % (str(wc), buffercode, compileinfo) + interpolated = py.code.Source(outputbuffer, + code % (str(wc), compileinfo)) channel = gw.remote_exec(interpolated) try: upath = channel.receive() From mwh at codespeak.net Thu Dec 21 16:38:28 2006 From: mwh at codespeak.net (mwh at codespeak.net) Date: Thu, 21 Dec 2006 16:38:28 +0100 (CET) Subject: [pypy-svn] r35936 - pypy/dist/pypy/translator/llvm Message-ID: <20061221153828.456391008E@code0.codespeak.net> Author: mwh Date: Thu Dec 21 16:38:26 2006 New Revision: 35936 Modified: pypy/dist/pypy/translator/llvm/funcnode.py Log: so it turns out there is a way to tell llvm that abort() will not return. this means i can delete some rather annoying code... Modified: pypy/dist/pypy/translator/llvm/funcnode.py ============================================================================== --- pypy/dist/pypy/translator/llvm/funcnode.py (original) +++ pypy/dist/pypy/translator/llvm/funcnode.py Thu Dec 21 16:38:26 2006 @@ -94,17 +94,7 @@ if self.bad_switch_block: codewriter.label('badswitch') codewriter._indent('call void %abort()') - rettype = self.graph.getreturnvar().concretetype - if rettype is lltype.Void: - codewriter._indent('ret void') - elif rettype is lltype.Bool: - codewriter._indent('ret bool false') - elif rettype is lltype.Float: - codewriter._indent('ret double 0.0') - elif isinstance(rettype, lltype.Ptr): - codewriter._indent('ret %s null'%(self.db.repr_type(rettype))) - else: - codewriter._indent('ret %s 0'%(self.db.repr_type(rettype))) + codewriter._indent('unreachable') codewriter.closefunc() def writeglobalconstants(self, codewriter): From mwh at codespeak.net Thu Dec 21 16:45:04 2006 From: mwh at codespeak.net (mwh at codespeak.net) Date: Thu, 21 Dec 2006 16:45:04 +0100 (CET) Subject: [pypy-svn] r35937 - in pypy/dist/pypy/translator/llvm: . test Message-ID: <20061221154504.5B28710098@code0.codespeak.net> Author: mwh Date: Thu Dec 21 16:45:02 2006 New Revision: 35937 Modified: pypy/dist/pypy/translator/llvm/database.py pypy/dist/pypy/translator/llvm/test/test_rtagged.py Log: so i finally figured out enough llvm syntax to get test_rtagged.py to pass. not sure about translate.py --objspace-std-withtaggedints yet. Modified: pypy/dist/pypy/translator/llvm/database.py ============================================================================== --- pypy/dist/pypy/translator/llvm/database.py (original) +++ pypy/dist/pypy/translator/llvm/database.py Thu Dec 21 16:45:02 2006 @@ -150,6 +150,9 @@ if value.ob is not None: self.prepare_constant(lltype.typeOf(value.ob), value.ob) return + + if isinstance(type_, lltype.Ptr) and isinstance(value._obj, int): + return if isinstance(type_, lltype.Ptr): type_ = type_.TO @@ -193,6 +196,9 @@ value = ptrvalue._obj + if isinstance(value, int): + return + # Only prepare root values at this point if isinstance(ct, lltype.Array) or isinstance(ct, lltype.Struct): p, c = lltype.parentlink(value) @@ -234,7 +240,11 @@ return self.primitives.repr(arg.concretetype, arg.value) else: assert isinstance(arg.value, lltype._ptr) - if not arg.value: + if isinstance(arg.value._obj, int): + rt = self.repr_type(arg.concretetype) + v = repr(arg.value._obj) + return 'cast (int %s to %s)'%(v, rt) + elif not arg.value: return 'null' else: node = self.obj2node[arg.value._obj] @@ -283,6 +293,9 @@ if value is None: return None, "%s null" % toptr + if isinstance(value, int): + return None, 'cast (int %s to %s)'%(value, toptr) + node = self.obj2node[value] ref = node.get_pbcref(toptr) return node, "%s %s" % (toptr, ref) Modified: pypy/dist/pypy/translator/llvm/test/test_rtagged.py ============================================================================== --- pypy/dist/pypy/translator/llvm/test/test_rtagged.py (original) +++ pypy/dist/pypy/translator/llvm/test/test_rtagged.py Thu Dec 21 16:45:02 2006 @@ -1,10 +1,6 @@ import sys, os from pypy.rlib.objectmodel import UnboxedValue -import py - -py.test.skip("not working at present") - class A(object): __slots__ = () def meth(self, x): From stephan at codespeak.net Thu Dec 21 17:05:25 2006 From: stephan at codespeak.net (stephan at codespeak.net) Date: Thu, 21 Dec 2006 17:05:25 +0100 (CET) Subject: [pypy-svn] r35938 - in pypy/dist/pypy/lib: . app_test Message-ID: <20061221160525.EFD921008F@code0.codespeak.net> Author: stephan Date: Thu Dec 21 17:05:24 2006 New Revision: 35938 Modified: pypy/dist/pypy/lib/app_test/test_stackless.py pypy/dist/pypy/lib/stackless_new.py Log: added some debug code to test_stackless.py and added 'labels' to tasklets/channels (non standard feature). py.test is behaving very strangely together with stackless. In order to see that, enable 'SHOW_STRANGE' in test_stackless.py. Two tests will fail and will have some debug messages. It looks like the two test are intertwined. Stange indeed. Modified: pypy/dist/pypy/lib/app_test/test_stackless.py ============================================================================== --- pypy/dist/pypy/lib/app_test/test_stackless.py (original) +++ pypy/dist/pypy/lib/app_test/test_stackless.py Thu Dec 21 17:05:24 2006 @@ -18,6 +18,12 @@ except ImportError, e: skip('cannot import stackless: %s' % (e,)) +SHOW_STRANGE = False + +def dprint(txt): + if SHOW_STRANGE: + print txt + def pypy_skip(txt): "don't skip, if we are running with CStackless" if not stackless_c: @@ -380,7 +386,6 @@ import sys b = stackless.bomb(*sys.exc_info()) assert b.type is ZeroDivisionError - print str(b.value) assert str(b.value).startswith('integer division') assert b.traceback is not None @@ -444,26 +449,42 @@ X_out.send(foo) X, Y = stackless.channel(), stackless.channel() - stackless.tasklet(pipe)(X, Y) + t = stackless.tasklet(pipe)(X, Y) stackless.run() X.send(42) assert Y.receive() == 42 def test_nested_pipe(self): + dprint('tnp ==== 1') def pipe(X, Y): + dprint('tnp_P ==== 1') foo = X.receive() + dprint('tnp_P ==== 2') Y.send(foo) + dprint('tnp_P ==== 3') def nest(X, Y): X2, Y2 = stackless.channel(), stackless.channel() t = stackless.tasklet(pipe)(X2, Y2) - X2.send(X.receive()) - Y.send(Y2.receive()) + dprint('tnp_N ==== 1') + X_Val = X.receive() + dprint('tnp_N ==== 2') + X2.send(X_Val) + dprint('tnp_N ==== 3') + Y2_Val = Y2.receive() + dprint('tnp_N ==== 4') + Y.send(Y2_Val) + dprint('tnp_N ==== 5') X, Y = stackless.channel(), stackless.channel() t1 = stackless.tasklet(nest)(X, Y) - X.send(42) - assert Y.receive() == 42 + X.send(13) + dprint('tnp ==== 2') + res = Y.receive() + dprint('tnp ==== 3') + assert res == 13 + if SHOW_STRANGE: + raise Exception('force prints') def test_wait_two(self): """ @@ -474,25 +495,43 @@ # some leftover tasklets in the queue are messing # things up. This test runs fine, when being alone # in a test file - pypy_skip("still problems with scheduling") - def sleep(X, Barrier): - Barrier.send((X, X.receive())) + if not SHOW_STRANGE: + pypy_skip("still problems with scheduling") + + def sleep(X, Y): + dprint('twt_S ==== 1') + value = X.receive() + dprint('twt_S ==== 2') + Y.send((X, value)) + dprint('twt_S ==== 3') def wait_two(X, Y, Ret_chan): Barrier = stackless.channel() stackless.tasklet(sleep)(X, Barrier) stackless.tasklet(sleep)(Y, Barrier) + dprint('twt_W ==== 1') ret = Barrier.receive() + dprint('twt_W ==== 2') if ret[0] == X: Ret_chan.send((1, ret[1])) else: Ret_chan.send((2, ret[1])) + dprint('twt_W ==== 3') + + X = stackless.channel() + Y = stackless.channel() + Ret_chan = stackless.channel() - X, Y, Ret_chan = stackless.channel(), stackless.channel(), stackless.channel() stackless.tasklet(wait_two)(X, Y, Ret_chan) + + dprint('twt ==== 1') Y.send(42) + + dprint('twt ==== 2') X.send(42) + dprint('twt ==== 3') value = Ret_chan.receive() + dprint('twt ==== 4') assert value == (2, 42) def test_noop(self): Modified: pypy/dist/pypy/lib/stackless_new.py ============================================================================== --- pypy/dist/pypy/lib/stackless_new.py (original) +++ pypy/dist/pypy/lib/stackless_new.py Thu Dec 21 17:05:24 2006 @@ -53,6 +53,7 @@ _last_task = next if _schedule_callback is not None: _schedule_callback(current, next) + assert not next.blocked next.switch() return current @@ -88,13 +89,14 @@ is resumed. If there is no waiting sender, the receiver is suspended. """ - def __init__(self): + def __init__(self, label=''): self.balance = 0 self.closing = False self.queue = deque() + self.label = label def __str__(self): - return 'channel(%s,%s)' % (self.balance, self.queue) + return 'channel[%s](%s,%s)' % (self.label, self.balance, self.queue) def close(self): """ @@ -184,23 +186,24 @@ New tasklets can be created with methods from the stackless module. """ - def __new__(cls, func=None): + def __new__(cls, func=None, label=''): return super(tasklet,cls).__new__(cls) - def __init__(self, func=None): + def __init__(self, func=None, label=''): super(tasklet, self).__init__() - self._init(func) + self._init(func, label) - def _init(self, func=None): + def _init(self, func=None, label=''): global _global_task_id self.tempval = func self.alive = False self.blocked = False - self.task_id = _global_task_id + self._task_id = _global_task_id + self.label = label _global_task_id += 1 def __str__(self): - return '' % (self.task_id, self.is_alive) + return '' % (self.label,self._task_id) __repr__ = __str__ @@ -365,8 +368,7 @@ return getattr(self._coro,attr) def __str__(self): - return '' % \ - (self.task_id, self.is_alive, self.is_zombie) + return '' % (self._task_id, self.is_alive) def __reduce__(self): return getmain, () @@ -378,7 +380,7 @@ _main_coroutine = _main_tasklet _main_tasklet = TaskletProxy(_main_tasklet) assert _main_tasklet.is_alive and not _main_tasklet.is_zombie - tasklet._init(_main_tasklet) + tasklet._init(_main_tasklet, label='main') _squeue = deque() _scheduler_append(_main_tasklet) From adim at codespeak.net Thu Dec 21 17:40:59 2006 From: adim at codespeak.net (adim at codespeak.net) Date: Thu, 21 Dec 2006 17:40:59 +0100 (CET) Subject: [pypy-svn] r35939 - in pypy/branch/ast-experiments/pypy/interpreter: . pyparser pyparser/test stablecompiler Message-ID: <20061221164059.1267010097@code0.codespeak.net> Author: adim Date: Thu Dec 21 17:40:55 2006 New Revision: 35939 Modified: pypy/branch/ast-experiments/pypy/interpreter/pycompiler.py pypy/branch/ast-experiments/pypy/interpreter/pyparser/astbuilder.py pypy/branch/ast-experiments/pypy/interpreter/pyparser/pythonparse.py pypy/branch/ast-experiments/pypy/interpreter/pyparser/pythonutil.py pypy/branch/ast-experiments/pypy/interpreter/pyparser/test/test_astbuilder.py pypy/branch/ast-experiments/pypy/interpreter/pyparser/test/test_astcompiler.py pypy/branch/ast-experiments/pypy/interpreter/pyparser/test/test_pytokenizer.py pypy/branch/ast-experiments/pypy/interpreter/stablecompiler/transformer.py Log: renamed get_pyparser_for_version to make_pyparser Modified: pypy/branch/ast-experiments/pypy/interpreter/pycompiler.py ============================================================================== --- pypy/branch/ast-experiments/pypy/interpreter/pycompiler.py (original) +++ pypy/branch/ast-experiments/pypy/interpreter/pycompiler.py Thu Dec 21 17:40:55 2006 @@ -200,10 +200,9 @@ the whole source after having only added a new '\n') """ def __init__(self, space): - from pyparser.pythonparse import get_pyparser_for_version - from pypy.tool.option import Options + from pyparser.pythonparse import make_pyparser PyCodeCompiler.__init__(self, space) - self.parser = get_pyparser_for_version(Options.version) + self.parser = make_pyparser() self.additional_rules = {} Modified: pypy/branch/ast-experiments/pypy/interpreter/pyparser/astbuilder.py ============================================================================== --- pypy/branch/ast-experiments/pypy/interpreter/pyparser/astbuilder.py (original) +++ pypy/branch/ast-experiments/pypy/interpreter/pyparser/astbuilder.py Thu Dec 21 17:40:55 2006 @@ -1062,6 +1062,7 @@ """A builder that directly produce the AST""" def __init__(self, parser=None, debug=0, space=None): + # XXX: parser must become mandatory if parser is None: from pythonparse import PYTHON_PARSER parser = pythonparse.PYTHON_PARSER Modified: pypy/branch/ast-experiments/pypy/interpreter/pyparser/pythonparse.py ============================================================================== --- pypy/branch/ast-experiments/pypy/interpreter/pyparser/pythonparse.py (original) +++ pypy/branch/ast-experiments/pypy/interpreter/pyparser/pythonparse.py Thu Dec 21 17:40:55 2006 @@ -173,14 +173,14 @@ -def get_pyparser_for_version(version): +def make_pyparser(version=Options.version): parser = PythonParser(predefined_symbols=symbol.sym_name) return build_parser_for_version(version, parser=parser) # unfortunately the command line options are not parsed yet -debug_print( "Loading grammar %s" % Options.version ) +# debug_print( "Loading grammar %s" % Options.version ) # XXX: remove PYTHON_PARSER -PYTHON_PARSER = get_pyparser_for_version(Options.version) +PYTHON_PARSER = make_pyparser() ## XXX BROKEN ## def grammar_rules( space ): Modified: pypy/branch/ast-experiments/pypy/interpreter/pyparser/pythonutil.py ============================================================================== --- pypy/branch/ast-experiments/pypy/interpreter/pyparser/pythonutil.py (original) +++ pypy/branch/ast-experiments/pypy/interpreter/pyparser/pythonutil.py Thu Dec 21 17:40:55 2006 @@ -69,19 +69,19 @@ def pypy_parse(source, mode='exec', lineno=False): - from pypy.interpreter.pyparser.pythonparse import PythonParser, get_pyparser_for_version + from pypy.interpreter.pyparser.pythonparse import PythonParser, make_pyparser from pypy.interpreter.pyparser.astbuilder import AstBuilder # parser = build_parser_for_version("2.4", PythonParser()) - parser = get_pyparser_for_version('2.4') + parser = make_pyparser('2.4') builder = TupleBuilder(parser) parser.parse_source(source, mode, builder) return builder.stack[-1].as_tuple(lineno) def source2ast(source, mode='exec', version='2.4', space=None): - from pypy.interpreter.pyparser.pythonparse import PythonParser, get_pyparser_for_version + from pypy.interpreter.pyparser.pythonparse import PythonParser, make_pyparser from pypy.interpreter.pyparser.astbuilder import AstBuilder - parser = get_pyparser_for_version(version) + parser = make_pyparser(version) builder = AstBuilder(parser, space=space) parser.parse_source(source, mode, builder) return builder Modified: pypy/branch/ast-experiments/pypy/interpreter/pyparser/test/test_astbuilder.py ============================================================================== --- pypy/branch/ast-experiments/pypy/interpreter/pyparser/test/test_astbuilder.py (original) +++ pypy/branch/ast-experiments/pypy/interpreter/pyparser/test/test_astbuilder.py Thu Dec 21 17:40:55 2006 @@ -1,5 +1,4 @@ import os -from pypy.tool.option import Options from pypy.interpreter.pyparser import pythonparse from pypy.interpreter.pyparser.astbuilder import AstBuilder @@ -210,8 +209,8 @@ builtin = dict(int=int, long=long, float=float, complex=complex) # Create parser from Grammar_stable, not current grammar. -stable_parser = pythonparse.get_pyparser_for_version('stable') -python_parser = pythonparse.get_pyparser_for_version(Options.version) # 'native') # 2.5a') +stable_parser = pythonparse.make_pyparser('stable') +python_parser = pythonparse.make_pyparser() # 'native') # 2.5a') def tuple_parse_expr(expr, target='single'): t = Transformer("dummyfile") Modified: pypy/branch/ast-experiments/pypy/interpreter/pyparser/test/test_astcompiler.py ============================================================================== --- pypy/branch/ast-experiments/pypy/interpreter/pyparser/test/test_astcompiler.py (original) +++ pypy/branch/ast-experiments/pypy/interpreter/pyparser/test/test_astcompiler.py Thu Dec 21 17:40:55 2006 @@ -39,7 +39,7 @@ return rcode # Create parser from Grammar_stable, not current grammar. -stable_parser = pythonparse.get_pyparser_for_version('stable') +stable_parser = pythonparse.make_pyparser('stable') def compile_with_testcompiler(expr, mode='exec', space=FakeSpace()): mode2 = 'exec' # xxx exec: single not really tested Modified: pypy/branch/ast-experiments/pypy/interpreter/pyparser/test/test_pytokenizer.py ============================================================================== --- pypy/branch/ast-experiments/pypy/interpreter/pyparser/test/test_pytokenizer.py (original) +++ pypy/branch/ast-experiments/pypy/interpreter/pyparser/test/test_pytokenizer.py Thu Dec 21 17:40:55 2006 @@ -1,7 +1,9 @@ from pypy.interpreter.pyparser.pythonlexer import Source, TokenError, \ match_encoding_declaration from pypy.interpreter.pyparser.grammar import Token, GrammarElement -from pypy.interpreter.pyparser.pythonparse import PYTHON_PARSER as P +from pypy.interpreter.pyparser.pythonparse import make_pyparser + +P = make_pyparser() EQUAL = P.EQUAL ENDMARKER = P.ENDMARKER Modified: pypy/branch/ast-experiments/pypy/interpreter/stablecompiler/transformer.py ============================================================================== --- pypy/branch/ast-experiments/pypy/interpreter/stablecompiler/transformer.py (original) +++ pypy/branch/ast-experiments/pypy/interpreter/stablecompiler/transformer.py Thu Dec 21 17:40:55 2006 @@ -26,7 +26,7 @@ # and replace OWNER, ORGANIZATION, and YEAR as appropriate. # make sure we import the parser with the correct grammar -from pypy.interpreter.pyparser.pythonparse import get_pyparser_for_version +from pypy.interpreter.pyparser.pythonparse import make_pyparser from pypy.interpreter.stablecompiler.ast import * import parser @@ -37,7 +37,7 @@ # stable_grammar, _ = pythonparse.get_grammar_file("stable") # stable_parser = pythonparse.python_grammar(stable_grammar) -stable_parser = get_pyparser_for_version('stable') +stable_parser = make_pyparser('stable') class symbol: pass From mwh at codespeak.net Thu Dec 21 19:01:13 2006 From: mwh at codespeak.net (mwh at codespeak.net) Date: Thu, 21 Dec 2006 19:01:13 +0100 (CET) Subject: [pypy-svn] r35940 - pypy/dist/pypy/translator/llvm Message-ID: <20061221180113.3A051100A7@code0.codespeak.net> Author: mwh Date: Thu Dec 21 19:01:11 2006 New Revision: 35940 Modified: pypy/dist/pypy/translator/llvm/database.py Log: one little fix to get a pypy-llvm with tagged ints. Modified: pypy/dist/pypy/translator/llvm/database.py ============================================================================== --- pypy/dist/pypy/translator/llvm/database.py (original) +++ pypy/dist/pypy/translator/llvm/database.py Thu Dec 21 19:01:11 2006 @@ -294,7 +294,7 @@ return None, "%s null" % toptr if isinstance(value, int): - return None, 'cast (int %s to %s)'%(value, toptr) + return None, '%s cast (int %s to %s)'%(toptr, value, toptr) node = self.obj2node[value] ref = node.get_pbcref(toptr) From mwh at codespeak.net Thu Dec 21 19:11:44 2006 From: mwh at codespeak.net (mwh at codespeak.net) Date: Thu, 21 Dec 2006 19:11:44 +0100 (CET) Subject: [pypy-svn] r35941 - in pypy/dist/pypy: config translator/llvm Message-ID: <20061221181144.2865F100AB@code0.codespeak.net> Author: mwh Date: Thu Dec 21 19:11:43 2006 New Revision: 35941 Modified: pypy/dist/pypy/config/translationoption.py pypy/dist/pypy/translator/llvm/buildllvm.py Log: make the decision on whether to compile llvm via c (for targets at least) a config option, defaulting to False. Modified: pypy/dist/pypy/config/translationoption.py ============================================================================== --- pypy/dist/pypy/config/translationoption.py (original) +++ pypy/dist/pypy/config/translationoption.py Thu Dec 21 19:11:43 2006 @@ -23,6 +23,9 @@ "cl": [("translation.type_system", "ootype")], }, cmdline="-b --backend"), + BoolOption("llvm_via_c", "compile llvm bytecode via C", + default=False, cmdline="--llvm-via-c", + requires=[("translation.backend", "llvm")]), ChoiceOption("gc", "Garbage Collection Strategy", ["boehm", "ref", "framework", "none", "stacklessgc", "exact_boehm"], Modified: pypy/dist/pypy/translator/llvm/buildllvm.py ============================================================================== --- pypy/dist/pypy/translator/llvm/buildllvm.py (original) +++ pypy/dist/pypy/translator/llvm/buildllvm.py Thu Dec 21 19:11:43 2006 @@ -61,7 +61,7 @@ profile=False, cleanup=False, use_gcc=True): if exe_name: - use_gcc = False #XXX trying to get of gcc (at least for standalones) + use_gcc = genllvm.config.translation.llvm_via_c # where we are building dirpath = llvmfile.dirpath() From mwh at codespeak.net Thu Dec 21 19:22:29 2006 From: mwh at codespeak.net (mwh at codespeak.net) Date: Thu, 21 Dec 2006 19:22:29 +0100 (CET) Subject: [pypy-svn] r35942 - pypy/dist/pypy/translator/llvm Message-ID: <20061221182229.33F4C100AD@code0.codespeak.net> Author: mwh Date: Thu Dec 21 19:22:28 2006 New Revision: 35942 Modified: pypy/dist/pypy/translator/llvm/buildllvm.py Log: a quick hack job to enable compiling llvm via c using gcc's profile directed optimization. is it possible to test this stuff some how? Modified: pypy/dist/pypy/translator/llvm/buildllvm.py ============================================================================== --- pypy/dist/pypy/translator/llvm/buildllvm.py (original) +++ pypy/dist/pypy/translator/llvm/buildllvm.py Thu Dec 21 19:22:28 2006 @@ -104,15 +104,28 @@ else: cmds.append("llc %s.bc -march=c -f -o %s.c" % (b, b)) if exe_name: - cmd = "gcc %s.c -c -O3 -pipe" % b - if profile: - cmd += ' -pg' + if genllvm.config.translation.profopt is not None: + cmd = "gcc -fprofile-generate %s.c -c -O3 -pipe -o %s.o" % (b, b) + cmds.append(cmd) + cmd = "gcc -fprofile-generate %s.o %s %s -lm -pipe -o %s_gen" % \ + (b, gc_libs_path, gc_libs, exe_name) + cmds.append(cmd) + cmds.append("./%s_gen %s"%(exe_name, genllvm.config.translation.profopt)) + cmds.append(cmd) + cmd = "gcc -fprofile-use %s.c -c -O3 -pipe -o %s.o" % (b, b) + cmds.append(cmd) + cmd = "gcc -fprofile-use %s.o %s %s -lm -pipe -o %s" % \ + (b, gc_libs_path, gc_libs, exe_name) else: - cmd += ' -fomit-frame-pointer' - cmds.append(cmd) - cmd = "gcc %s.o %s %s -lm -pipe -o %s" % (b, gc_libs_path, gc_libs, exe_name) - if profile: - cmd += ' -pg' + cmd = "gcc %s.c -c -O3 -pipe" % b + if profile: + cmd += ' -pg' + else: + cmd += ' -fomit-frame-pointer' + cmds.append(cmd) + cmd = "gcc %s.o %s %s -lm -pipe -o %s" % (b, gc_libs_path, gc_libs, exe_name) + if profile: + cmd += ' -pg' cmds.append(cmd) source_files.append("%s.c" % b) From mwh at codespeak.net Thu Dec 21 21:51:57 2006 From: mwh at codespeak.net (mwh at codespeak.net) Date: Thu, 21 Dec 2006 21:51:57 +0100 (CET) Subject: [pypy-svn] r35943 - pypy/dist/pypy/config Message-ID: <20061221205157.8DA6D1008A@code0.codespeak.net> Author: mwh Date: Thu Dec 21 21:51:56 2006 New Revision: 35943 Modified: pypy/dist/pypy/config/pypyoption.py Log: add a --llvm-faassen that is like --faassen but targets llvm, compiled via C with profiling optimizations. probably the fastest pypy yet, but boy does it take a while to get it. Modified: pypy/dist/pypy/config/pypyoption.py ============================================================================== --- pypy/dist/pypy/config/pypyoption.py (original) +++ pypy/dist/pypy/config/pypyoption.py Thu Dec 21 21:51:56 2006 @@ -134,7 +134,15 @@ ("objspace.std.withsmallint", True), ("objspace.std.withrangelist", True), ], - cmdline="--faassen") + cmdline="--faassen"), + + BoolOption("llvmallopts", + "enable all optimizations, and use llvm compiled via C", + default=False, + requires=[("objspace.std.allopts", True), + ("translation.llvm_via_c", True), + ("translation.backend", "llvm")], + cmdline="--llvm-faassen"), ]), BoolOption("lowmem", "Try to use little memory during translation", default=False, cmdline="--lowmem", From mwh at codespeak.net Thu Dec 21 21:54:51 2006 From: mwh at codespeak.net (mwh at codespeak.net) Date: Thu, 21 Dec 2006 21:54:51 +0100 (CET) Subject: [pypy-svn] r35944 - pypy/dist/pypy/translator/llvm Message-ID: <20061221205451.A984510091@code0.codespeak.net> Author: mwh Date: Thu Dec 21 21:54:50 2006 New Revision: 35944 Modified: pypy/dist/pypy/translator/llvm/buildllvm.py Log: oops, this linked the profile generate executable twice, for no very good reason Modified: pypy/dist/pypy/translator/llvm/buildllvm.py ============================================================================== --- pypy/dist/pypy/translator/llvm/buildllvm.py (original) +++ pypy/dist/pypy/translator/llvm/buildllvm.py Thu Dec 21 21:54:50 2006 @@ -111,7 +111,6 @@ (b, gc_libs_path, gc_libs, exe_name) cmds.append(cmd) cmds.append("./%s_gen %s"%(exe_name, genllvm.config.translation.profopt)) - cmds.append(cmd) cmd = "gcc -fprofile-use %s.c -c -O3 -pipe -o %s.o" % (b, b) cmds.append(cmd) cmd = "gcc -fprofile-use %s.o %s %s -lm -pipe -o %s" % \ From mwh at codespeak.net Fri Dec 22 11:02:24 2006 From: mwh at codespeak.net (mwh at codespeak.net) Date: Fri, 22 Dec 2006 11:02:24 +0100 (CET) Subject: [pypy-svn] r35945 - in pypy/dist/pypy/objspace/std: . test Message-ID: <20061222100224.A3C0710082@code0.codespeak.net> Author: mwh Date: Fri Dec 22 11:02:21 2006 New Revision: 35945 Modified: pypy/dist/pypy/objspace/std/strjoinobject.py pypy/dist/pypy/objspace/std/test/test_strjoinobject.py Log: fix a bug in add_StringJoin_StringJoin that was identical to the last bug fixed in add_StringJoin_String. Modified: pypy/dist/pypy/objspace/std/strjoinobject.py ============================================================================== --- pypy/dist/pypy/objspace/std/strjoinobject.py (original) +++ pypy/dist/pypy/objspace/std/strjoinobject.py Fri Dec 22 11:02:21 2006 @@ -48,6 +48,8 @@ return w_str.force() def add__StringJoin_StringJoin(space, w_self, w_other): + if len(w_self.joined_strs) > w_self.until: + w_self.force() w_self.joined_strs.extend(w_other.joined_strs) return W_StringJoinObject(w_self.joined_strs) Modified: pypy/dist/pypy/objspace/std/test/test_strjoinobject.py ============================================================================== --- pypy/dist/pypy/objspace/std/test/test_strjoinobject.py (original) +++ pypy/dist/pypy/objspace/std/test/test_strjoinobject.py Fri Dec 22 11:02:21 2006 @@ -42,3 +42,16 @@ r = "c" + "d" t = s + r assert len(s) == 2 + + def test_add_strjoin_strjoin(self): + # make three strjoin objects + s = 'a' + 'b' + t = 'c' + 'd' + u = 'e' + 'f' + + # add two different strjoins to the same string + v = s + t + w = s + u + + # check that insanity hasn't resulted. + assert len(v) == len(w) == 4 From ericvrp at codespeak.net Fri Dec 22 11:59:30 2006 From: ericvrp at codespeak.net (ericvrp at codespeak.net) Date: Fri, 22 Dec 2006 11:59:30 +0100 (CET) Subject: [pypy-svn] r35947 - pypy/extradoc/sprintinfo/leysin-winter-2007 Message-ID: <20061222105930.5345A10086@code0.codespeak.net> Author: ericvrp Date: Fri Dec 22 11:59:27 2006 New Revision: 35947 Modified: pypy/extradoc/sprintinfo/leysin-winter-2007/people.txt Log: My Leysin dates, flight is booked. Modified: pypy/extradoc/sprintinfo/leysin-winter-2007/people.txt ============================================================================== --- pypy/extradoc/sprintinfo/leysin-winter-2007/people.txt (original) +++ pypy/extradoc/sprintinfo/leysin-winter-2007/people.txt Fri Dec 22 11:59:27 2006 @@ -20,7 +20,7 @@ Niko Matsakis 9th-14th Ermina Antonio Cuni 7th-15th Ermina Maciej Fijalkowski 6th-17th? Ermina -Eric van Riet Paap 10th?-14th? Ermina +Eric van Riet Paap 10th-14th Ermina Jacob Hallen 5th-15th Ermina Laura Creighton 5th-15th Ermina ==================== ============== ===================== From mwh at codespeak.net Fri Dec 22 14:12:46 2006 From: mwh at codespeak.net (mwh at codespeak.net) Date: Fri, 22 Dec 2006 14:12:46 +0100 (CET) Subject: [pypy-svn] r35950 - pypy/dist/pypy/config Message-ID: <20061222131246.C10711007E@code0.codespeak.net> Author: mwh Date: Fri Dec 22 14:12:34 2006 New Revision: 35950 Modified: pypy/dist/pypy/config/pypyoption.py Log: remove the strjoin option from --faassen; still buggy :( Modified: pypy/dist/pypy/config/pypyoption.py ============================================================================== --- pypy/dist/pypy/config/pypyoption.py (original) +++ pypy/dist/pypy/config/pypyoption.py Fri Dec 22 14:12:34 2006 @@ -123,13 +123,13 @@ default=False, cmdline="--oldstyle"), BoolOption("allopts", - "enable all optimizations", + "enable all thought-to-be-working optimizations", default=False, requires=[("objspace.opcodes.CALL_LIKELY_BUILTIN", True), ("translation.withsmallfuncsets", 5), ("translation.profopt", "-c 'from richards import main;main(); from test import pystone; pystone.main()'"), - ("objspace.std.withstrjoin", True), +# ("objspace.std.withstrjoin", True), ("objspace.std.withstrslice", True), ("objspace.std.withsmallint", True), ("objspace.std.withrangelist", True), From mwh at codespeak.net Fri Dec 22 14:49:11 2006 From: mwh at codespeak.net (mwh at codespeak.net) Date: Fri, 22 Dec 2006 14:49:11 +0100 (CET) Subject: [pypy-svn] r35954 - in pypy/dist/pypy/objspace/std: . test Message-ID: <20061222134911.E9DC71007F@code0.codespeak.net> Author: mwh Date: Fri Dec 22 14:49:08 2006 New Revision: 35954 Modified: pypy/dist/pypy/objspace/std/strjoinobject.py pypy/dist/pypy/objspace/std/test/test_strjoinobject.py Log: fix more bugs in strjoins Modified: pypy/dist/pypy/objspace/std/strjoinobject.py ============================================================================== --- pypy/dist/pypy/objspace/std/strjoinobject.py (original) +++ pypy/dist/pypy/objspace/std/strjoinobject.py Fri Dec 22 14:49:08 2006 @@ -13,8 +13,8 @@ until = len(joined_strs) w_self.until = until - def force(w_self): - if w_self.until == 1: + def force(w_self, always=False): + if w_self.until == 1 and not always: return w_self.joined_strs[0] res = "".join(w_self.joined_strs[:w_self.until]) w_self.joined_strs = [res] @@ -49,13 +49,13 @@ def add__StringJoin_StringJoin(space, w_self, w_other): if len(w_self.joined_strs) > w_self.until: - w_self.force() + w_self.force(True) w_self.joined_strs.extend(w_other.joined_strs) return W_StringJoinObject(w_self.joined_strs) def add__StringJoin_String(space, w_self, w_other): if len(w_self.joined_strs) > w_self.until: - w_self.force() + w_self.force(True) other = space.str_w(w_other) w_self.joined_strs.append(other) return W_StringJoinObject(w_self.joined_strs) Modified: pypy/dist/pypy/objspace/std/test/test_strjoinobject.py ============================================================================== --- pypy/dist/pypy/objspace/std/test/test_strjoinobject.py (original) +++ pypy/dist/pypy/objspace/std/test/test_strjoinobject.py Fri Dec 22 14:49:08 2006 @@ -55,3 +55,10 @@ # check that insanity hasn't resulted. assert len(v) == len(w) == 4 + + def test_more_adding_fun(self): + s = 'a' + 'b' # s is a strjoin now + t = s + 'c' # this calls s.force() which sets s.until to 1 + u = s + 'd' + v = s + 'e' + assert v == 'abe' # meaning u is abcd From mwh at codespeak.net Fri Dec 22 15:04:39 2006 From: mwh at codespeak.net (mwh at codespeak.net) Date: Fri, 22 Dec 2006 15:04:39 +0100 (CET) Subject: [pypy-svn] r35955 - pypy/dist/pypy/objspace/std Message-ID: <20061222140439.D808C10086@code0.codespeak.net> Author: mwh Date: Fri Dec 22 15:04:35 2006 New Revision: 35955 Modified: pypy/dist/pypy/objspace/std/typeobject.py Log: add missing argument to W_TypeObject.unwrap. found by having changes that annotated a call to unwrap, a different kind of problem... Modified: pypy/dist/pypy/objspace/std/typeobject.py ============================================================================== --- pypy/dist/pypy/objspace/std/typeobject.py (original) +++ pypy/dist/pypy/objspace/std/typeobject.py Fri Dec 22 15:04:35 2006 @@ -311,7 +311,7 @@ newdic.initialize_content(dictspec) return W_DictProxyObject(newdic) - def unwrap(w_self): + def unwrap(w_self, space): if w_self.instancetypedef.fakedcpytype is not None: return w_self.instancetypedef.fakedcpytype from pypy.objspace.std.model import UnwrapError From mwh at codespeak.net Fri Dec 22 15:46:57 2006 From: mwh at codespeak.net (mwh at codespeak.net) Date: Fri, 22 Dec 2006 15:46:57 +0100 (CET) Subject: [pypy-svn] r35956 - in pypy/dist/pypy: interpreter objspace/std Message-ID: <20061222144657.0A71E10088@code0.codespeak.net> Author: mwh Date: Fri Dec 22 15:46:55 2006 New Revision: 35956 Modified: pypy/dist/pypy/interpreter/baseobjspace.py pypy/dist/pypy/interpreter/eval.py pypy/dist/pypy/interpreter/gateway.py pypy/dist/pypy/interpreter/pycode.py pypy/dist/pypy/objspace/std/fake.py pypy/dist/pypy/objspace/std/objspace.py Log: move frame creation onto the space Modified: pypy/dist/pypy/interpreter/baseobjspace.py ============================================================================== --- pypy/dist/pypy/interpreter/baseobjspace.py (original) +++ pypy/dist/pypy/interpreter/baseobjspace.py Fri Dec 22 15:46:55 2006 @@ -404,6 +404,11 @@ self.default_compiler = compiler return compiler + def createframe(self, code, w_globals, closure=None): + "Create an empty PyFrame suitable for this code object." + from pypy.interpreter import pyframe + return pyframe.PyFrame(self, code, w_globals, closure) + # Following is a friendly interface to common object space operations # that can be defined in term of more primitive ones. Subclasses # may also override specific functions for performance. Modified: pypy/dist/pypy/interpreter/eval.py ============================================================================== --- pypy/dist/pypy/interpreter/eval.py (original) +++ pypy/dist/pypy/interpreter/eval.py Fri Dec 22 15:46:55 2006 @@ -15,13 +15,10 @@ def __init__(self, co_name): self.co_name = co_name - def create_frame(self, space, w_globals, closure=None): - "Create an empty frame object suitable for evaluation of this code." - raise TypeError, "abstract" - def exec_code(self, space, w_globals, w_locals): "Implements the 'exec' statement." - frame = self.create_frame(space, w_globals, None) + # this should be on PyCode? + frame = space.createframe(self, w_globals, None) frame.setdictscope(w_locals) return frame.run() @@ -52,8 +49,8 @@ return None def funcrun(self, func, args): - frame = self.create_frame(func.space, func.w_func_globals, - func.closure) + frame = func.space.createframe(self, func.w_func_globals, + func.closure) sig = self.signature() scope_w = args.parse(func.name, sig, func.defs_w) frame.setfastscope(scope_w) Modified: pypy/dist/pypy/interpreter/gateway.py ============================================================================== --- pypy/dist/pypy/interpreter/gateway.py (original) +++ pypy/dist/pypy/interpreter/gateway.py Fri Dec 22 15:46:55 2006 @@ -438,9 +438,6 @@ self.__class__ = globals()['BuiltinCode%d' % arity] setattr(self, 'fastfunc_%d' % arity, fastfunc) - def create_frame(self, space, w_globals, closure=None): - raise NotImplementedError - def signature(self): return self.sig Modified: pypy/dist/pypy/interpreter/pycode.py ============================================================================== --- pypy/dist/pypy/interpreter/pycode.py (original) +++ pypy/dist/pypy/interpreter/pycode.py Fri Dec 22 15:46:55 2006 @@ -172,14 +172,14 @@ def fastcall_0(self, space, w_func): if self.do_fastcall == 0: - frame = self.create_frame(space, w_func.w_func_globals, + frame = space.createframe(self, w_func.w_func_globals, w_func.closure) return frame.run() return None def fastcall_1(self, space, w_func, w_arg): if self.do_fastcall == 1: - frame = self.create_frame(space, w_func.w_func_globals, + frame = space.createframe(self, w_func.w_func_globals, w_func.closure) frame.fastlocals_w[0] = w_arg # frame.setfastscope([w_arg]) return frame.run() @@ -187,7 +187,7 @@ def fastcall_2(self, space, w_func, w_arg1, w_arg2): if self.do_fastcall == 2: - frame = self.create_frame(space, w_func.w_func_globals, + frame = space.createframe(self, w_func.w_func_globals, w_func.closure) frame.fastlocals_w[0] = w_arg1 # frame.setfastscope([w_arg]) frame.fastlocals_w[1] = w_arg2 @@ -196,8 +196,8 @@ def fastcall_3(self, space, w_func, w_arg1, w_arg2, w_arg3): if self.do_fastcall == 3: - frame = self.create_frame(space, w_func.w_func_globals, - w_func.closure) + frame = space.createframe(self, w_func.w_func_globals, + w_func.closure) frame.fastlocals_w[0] = w_arg1 # frame.setfastscope([w_arg]) frame.fastlocals_w[1] = w_arg2 frame.fastlocals_w[2] = w_arg3 @@ -206,8 +206,8 @@ def fastcall_4(self, space, w_func, w_arg1, w_arg2, w_arg3, w_arg4): if self.do_fastcall == 4: - frame = self.create_frame(space, w_func.w_func_globals, - w_func.closure) + frame = space.createframe(self, w_func.w_func_globals, + w_func.closure) frame.fastlocals_w[0] = w_arg1 # frame.setfastscope([w_arg]) frame.fastlocals_w[1] = w_arg2 frame.fastlocals_w[2] = w_arg3 @@ -216,7 +216,7 @@ return None def funcrun(self, func, args): - frame = self.create_frame(self.space, func.w_func_globals, + frame = self.space.createframe(self, func.w_func_globals, func.closure) sig = self._signature # speed hack @@ -225,11 +225,6 @@ frame.init_cells() return frame.run() - def create_frame(self, space, w_globals, closure=None): - "Create an empty PyFrame suitable for this code object." - from pypy.interpreter import pyframe - return pyframe.PyFrame(space, self, w_globals, closure) - def getvarnames(self): return self.co_varnames Modified: pypy/dist/pypy/objspace/std/fake.py ============================================================================== --- pypy/dist/pypy/objspace/std/fake.py (original) +++ pypy/dist/pypy/objspace/std/fake.py Fri Dec 22 15:46:55 2006 @@ -134,8 +134,6 @@ eval.Code.__init__(self, getattr(cpy_callable, '__name__', '?')) self.cpy_callable = cpy_callable assert callable(cpy_callable), cpy_callable - def create_frame(self, space, w_globals, closure=None): - return CPythonFakeFrame(space, self, w_globals) def signature(self): return [], 'args', 'kwds' Modified: pypy/dist/pypy/objspace/std/objspace.py ============================================================================== --- pypy/dist/pypy/objspace/std/objspace.py (original) +++ pypy/dist/pypy/objspace/std/objspace.py Fri Dec 22 15:46:55 2006 @@ -12,6 +12,7 @@ from pypy.objspace.descroperation import DescrOperation from pypy.objspace.std import stdtypedef from pypy.rlib.rarithmetic import base_int +from pypy.rlib.objectmodel import we_are_translated import sys import os import __builtin__ @@ -227,6 +228,13 @@ ec._py_repr = self.newdict() return ec + def createframe(self, code, w_globals, closure=None): + from pypy.objspace.std.fake import CPythonFakeCode, CPythonFakeFrame + if not we_are_translated() and isinstance(code, CPythonFakeCode): + return CPythonFakeFrame(self, code, w_globals) + else: + return ObjSpace.createframe(self, code, w_globals, closure) + def gettypefor(self, cls): return self.gettypeobject(cls.typedef) From mwh at codespeak.net Fri Dec 22 15:56:47 2006 From: mwh at codespeak.net (mwh at codespeak.net) Date: Fri, 22 Dec 2006 15:56:47 +0100 (CET) Subject: [pypy-svn] r35957 - pypy/dist/pypy/config Message-ID: <20061222145647.44B7510072@code0.codespeak.net> Author: mwh Date: Fri Dec 22 15:56:45 2006 New Revision: 35957 Modified: pypy/dist/pypy/config/pypyoption.py Log: strjoins seem to be working again Modified: pypy/dist/pypy/config/pypyoption.py ============================================================================== --- pypy/dist/pypy/config/pypyoption.py (original) +++ pypy/dist/pypy/config/pypyoption.py Fri Dec 22 15:56:45 2006 @@ -129,7 +129,7 @@ ("translation.withsmallfuncsets", 5), ("translation.profopt", "-c 'from richards import main;main(); from test import pystone; pystone.main()'"), -# ("objspace.std.withstrjoin", True), + ("objspace.std.withstrjoin", True), ("objspace.std.withstrslice", True), ("objspace.std.withsmallint", True), ("objspace.std.withrangelist", True), From mwh at codespeak.net Fri Dec 22 15:57:37 2006 From: mwh at codespeak.net (mwh at codespeak.net) Date: Fri, 22 Dec 2006 15:57:37 +0100 (CET) Subject: [pypy-svn] r35958 - pypy/dist/pypy/objspace/fake Message-ID: <20061222145737.6485F10086@code0.codespeak.net> Author: mwh Date: Fri Dec 22 15:57:36 2006 New Revision: 35958 Modified: pypy/dist/pypy/objspace/fake/objspace.py Log: adapt to the change in signature of newdict Modified: pypy/dist/pypy/objspace/fake/objspace.py ============================================================================== --- pypy/dist/pypy/objspace/fake/objspace.py (original) +++ pypy/dist/pypy/objspace/fake/objspace.py Fri Dec 22 15:57:36 2006 @@ -86,7 +86,8 @@ newint = make_dummy() newlong = make_dummy() newfloat = make_dummy() - newdict = make_dummy() + def newdict(self, track_builtin_shadowing=False): + return self.newfloat() newlist = make_dummy() emptylist = make_dummy() newtuple = make_dummy() From mwh at codespeak.net Fri Dec 22 16:10:19 2006 From: mwh at codespeak.net (mwh at codespeak.net) Date: Fri, 22 Dec 2006 16:10:19 +0100 (CET) Subject: [pypy-svn] r35960 - in pypy/dist/pypy/objspace/flow: . test Message-ID: <20061222151019.A1EB710093@code0.codespeak.net> Author: mwh Date: Fri Dec 22 16:10:18 2006 New Revision: 35960 Modified: pypy/dist/pypy/objspace/flow/flowcontext.py pypy/dist/pypy/objspace/flow/test/test_framestate.py Log: argh, forgot to check this in Modified: pypy/dist/pypy/objspace/flow/flowcontext.py ============================================================================== --- pypy/dist/pypy/objspace/flow/flowcontext.py (original) +++ pypy/dist/pypy/objspace/flow/flowcontext.py Fri Dec 22 16:10:18 2006 @@ -1,5 +1,6 @@ from pypy.interpreter.executioncontext import ExecutionContext from pypy.interpreter.error import OperationError +from pypy.interpreter import pyframe from pypy.objspace.flow.model import * from pypy.objspace.flow.framestate import FrameState @@ -218,8 +219,8 @@ # create an empty frame suitable for the code object # while ignoring any operation like the creation of the locals dict self.recorder = [] - frame = self.code.create_frame(self.space, self.w_globals, - self.closure) + frame = pyframe.PyFrame(self.space, self.code, + self.w_globals, self.closure) frame.last_instr = 0 return frame Modified: pypy/dist/pypy/objspace/flow/test/test_framestate.py ============================================================================== --- pypy/dist/pypy/objspace/flow/test/test_framestate.py (original) +++ pypy/dist/pypy/objspace/flow/test/test_framestate.py Fri Dec 22 16:10:18 2006 @@ -20,7 +20,7 @@ code = func.func_code code = PyCode._from_code(self.space, code) w_globals = Constant({}) # space.newdict() - frame = code.create_frame(space, w_globals) + frame = self.space.createframe(code, w_globals) formalargcount = code.getformalargcount() dummy = Constant(None) From mwh at codespeak.net Fri Dec 22 17:26:44 2006 From: mwh at codespeak.net (mwh at codespeak.net) Date: Fri, 22 Dec 2006 17:26:44 +0100 (CET) Subject: [pypy-svn] r35961 - in pypy/dist/pypy: interpreter objspace/std Message-ID: <20061222162644.CC4EC1008B@code0.codespeak.net> Author: mwh Date: Fri Dec 22 17:26:43 2006 New Revision: 35961 Modified: pypy/dist/pypy/interpreter/pyopcode.py pypy/dist/pypy/objspace/std/objspace.py Log: place a flow space friendly implementation of CALL_LIKELY_BUILTIN into interpreter/pyopcode.py and move the optimized, stdobjspace-dependent implementation into objspace/std, where it belongs. thanks samuele for the prodding :-) now to find why the co_code & friends attributes are moving up to eval.Code... Modified: pypy/dist/pypy/interpreter/pyopcode.py ============================================================================== --- pypy/dist/pypy/interpreter/pyopcode.py (original) +++ pypy/dist/pypy/interpreter/pyopcode.py Fri Dec 22 17:26:43 2006 @@ -602,18 +602,20 @@ return f.LOAD_GLOBAL(nameindex) # fall-back - def LOAD_GLOBAL(f, nameindex, *ignored): - w_varname = f.getname_w(nameindex) + def _load_global(f, w_varname): w_value = f.space.finditem(f.w_globals, w_varname) if w_value is None: # not in the globals, now look in the built-ins w_value = f.builtin.getdictvalue(f.space, w_varname) if w_value is None: - varname = f.getname_u(nameindex) + varname = f.space.str_w(w_varname) message = "global name '%s' is not defined" % varname raise OperationError(f.space.w_NameError, f.space.wrap(message)) - f.valuestack.push(w_value) + return w_value + + def LOAD_GLOBAL(f, nameindex, *ignored): + f.valuestack.push(f._load_global(f.getname_w(nameindex))) def DELETE_FAST(f, varindex, *ignored): if f.fastlocals_w[varindex] is None: @@ -875,31 +877,13 @@ pass def CALL_LIKELY_BUILTIN(f, oparg, *ignored): - from pypy.module.__builtin__ import OPTIMIZED_BUILTINS, Module - from pypy.objspace.std.dictmultiobject import W_DictMultiObject - w_globals = f.w_globals - num = oparg >> 8 - assert isinstance(w_globals, W_DictMultiObject) - w_value = w_globals.implementation.get_builtin_indexed(num) - if w_value is None: - w_builtins = f.builtin - assert isinstance(w_builtins, Module) - w_builtin_dict = w_builtins.w_dict - assert isinstance(w_builtin_dict, W_DictMultiObject) - w_value = w_builtin_dict.implementation.get_builtin_indexed(num) -## if w_value is not None: -## print "CALL_LIKELY_BUILTIN fast" - if w_value is None: - varname = OPTIMIZED_BUILTINS[num] - message = "global name '%s' is not defined" % varname - raise OperationError(f.space.w_NameError, - f.space.wrap(message)) - nargs = oparg & 0xff - w_function = w_value + # overridden by faster version in the standard object space. + from pypy.module.__builtin__ import OPTIMIZED_BUILTINS + w_varname = f.space.wrap(OPTIMIZED_BUILTINS[oparg >> 8]) + w_function = f._load_global(w_varname) + nargs = oparg&0xFF try: w_result = f.space.call_valuestack(w_function, nargs, f.valuestack) - # XXX XXX fix the problem of resume points! - #rstack.resume_point("CALL_FUNCTION", f, nargs, returns=w_result) finally: f.valuestack.drop(nargs) f.valuestack.push(w_result) Modified: pypy/dist/pypy/objspace/std/objspace.py ============================================================================== --- pypy/dist/pypy/objspace/std/objspace.py (original) +++ pypy/dist/pypy/objspace/std/objspace.py Fri Dec 22 17:26:43 2006 @@ -36,6 +36,38 @@ assert issubclass(implcls, W_Object) _registered_implementations[implcls] = True +from pypy.interpreter import pyframe + +class StdObjSpaceFrame(pyframe.PyFrame): + def CALL_LIKELY_BUILTIN(f, oparg, *ignored): + from pypy.module.__builtin__ import OPTIMIZED_BUILTINS, Module + from pypy.objspace.std.dictmultiobject import W_DictMultiObject + w_globals = f.w_globals + num = oparg >> 8 + assert isinstance(w_globals, W_DictMultiObject) + w_value = w_globals.implementation.get_builtin_indexed(num) + if w_value is None: + w_builtins = f.builtin + assert isinstance(w_builtins, Module) + w_builtin_dict = w_builtins.w_dict + assert isinstance(w_builtin_dict, W_DictMultiObject) + w_value = w_builtin_dict.implementation.get_builtin_indexed(num) +## if w_value is not None: +## print "CALL_LIKELY_BUILTIN fast" + if w_value is None: + varname = OPTIMIZED_BUILTINS[num] + message = "global name '%s' is not defined" % varname + raise OperationError(f.space.w_NameError, + f.space.wrap(message)) + nargs = oparg & 0xff + w_function = w_value + try: + w_result = f.space.call_valuestack(w_function, nargs, f.valuestack) + # XXX XXX fix the problem of resume points! + #rstack.resume_point("CALL_FUNCTION", f, nargs, returns=w_result) + finally: + f.valuestack.drop(nargs) + f.valuestack.push(w_result) ################################################################## @@ -233,7 +265,7 @@ if not we_are_translated() and isinstance(code, CPythonFakeCode): return CPythonFakeFrame(self, code, w_globals) else: - return ObjSpace.createframe(self, code, w_globals, closure) + return StdObjSpaceFrame(self, code, w_globals, closure) def gettypefor(self, cls): return self.gettypeobject(cls.typedef) From mwh at codespeak.net Fri Dec 22 18:48:33 2006 From: mwh at codespeak.net (mwh at codespeak.net) Date: Fri, 22 Dec 2006 18:48:33 +0100 (CET) Subject: [pypy-svn] r35962 - pypy/dist/pypy/interpreter Message-ID: <20061222174833.E01CD10082@code0.codespeak.net> Author: mwh Date: Fri Dec 22 18:48:31 2006 New Revision: 35962 Modified: pypy/dist/pypy/interpreter/pyframe.py Log: this is enough to stop various attributes moving up from PyCode to Code, but it's probably not the cleanest solution. Modified: pypy/dist/pypy/interpreter/pyframe.py ============================================================================== --- pypy/dist/pypy/interpreter/pyframe.py (original) +++ pypy/dist/pypy/interpreter/pyframe.py Fri Dec 22 18:48:31 2006 @@ -47,6 +47,7 @@ instr_prev = -1 def __init__(self, space, code, w_globals, closure): + assert isinstance(code, pycode.PyCode) self.pycode = code eval.Frame.__init__(self, space, w_globals, code.co_nlocals) # XXX hack: FlowSpace directly manipulates stack From arigo at codespeak.net Fri Dec 22 23:01:39 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 22 Dec 2006 23:01:39 +0100 (CET) Subject: [pypy-svn] r35963 - pypy/dist/pypy/doc Message-ID: <20061222220139.25F1810086@code0.codespeak.net> Author: arigo Date: Fri Dec 22 23:01:36 2006 New Revision: 35963 Modified: pypy/dist/pypy/doc/jit.txt Log: A couple of new sections filled. Modified: pypy/dist/pypy/doc/jit.txt ============================================================================== --- pypy/dist/pypy/doc/jit.txt (original) +++ pypy/dist/pypy/doc/jit.txt Fri Dec 22 23:01:36 2006 @@ -615,17 +615,209 @@ Calls and inlining --------------------- -... +...green call... red call and inlining effect... gray call, yellow call... + -Virtual Containers +Virtual structures -------------------- -...vstructs, vlist, vdict... +The support code introduced by the timeshifter contains an optimization +for all memory allocations that would normally have to occur at +run-time: it makes these allocations lazy. A *virtual structure* is +such a lazily-allocated run-time data structure. + +The hint-annotator gives the color red to the result of a malloc +operation. However, the timeshifter turns the malloc into a pure +compile-time operation that returns a special PtrRedBox object. The +PtrRedBox contains neither a compile-time value (because its value as a +pointer is not a compile-time constant) nor a run-time value (because no +residual code was generated to perform the malloc yet, so no run-time +machine code register contains the pointer's value). Instead, the +PtrRedBox references a *virtual structure* object that describes what +shape and what values the structure would contain at run-time; the +values are themselves further RedBoxes. + +For example, in the following code:: + + obj = MyClass() + obj.x = somevalue + ... + print obj.x + +all the variables are red. At compile-time, the malloc corresponding to +the instantiation of ``MyClass`` returns a PtrRedBox with a virtual +structure. In the next line, the attribute assignment stores the RedBox +corresponding to ``somevalue`` into the virtual structure. Later on, +reading ``obj.x`` reads out the same RedBox out of the virtual +structure. This is all done without generating any residual code; the +machine code register that holds ``somevalue`` at run-time simply stays +around and is used directly in the ``print`` statement. + +The above example is of course too simple to reflect the complex control +flow patterns of real-life programs. In some cases, merge points +prevent us from following virtual structures. Indeed, consider:: + + if condition: + obj = MyFirstClass() + else: + obj = MySecondClass() + +Following the ``if`` statement, the control flow graph contains such a +merge point. Assume first that the ``condition`` is a compile-time +constant. In this case, only one path is considered anyway, so ``obj`` +is propagated into the rest of the code as a PtrRedBox with a specific +virtual structure. But assume now that ``condition`` is not a +compile-time constant. In this case, in each incoming path the variable +``obj`` contains a PtrRedBox with a different type of virtual structure. +To avoid an explosion of the number of cases to consider, the +compile-time logic *forces* the virtual structures at this point, +i.e. it generates code that actually allocates them at run-time. For +the rest of the code, the PtrRedBox changes its status and becomes a +regular run-time PtrRedBox. + +Another case in which a virtual structure must be forced is when the +pointer escapes to some uncontrolled place, e.g. when it is stored into +a (non-virtual) run-time structure. + +Note that the virtual structure object itself stores enough information +to know exactly the run-time type it was allocated with. This is +necessary because the PtrRedBox itself might be cast up to a less +precise pointer type, without necessarily forcing the virtual structure. +This is the case in the previous example: the inferred type for ``obj`` +in the rest of the code is the less precise common base class of +``MyFirstClass`` and ``MySecondClass``, whereas if ``condition`` is a +compile-time constant then the virtual structure can carry the precise +class of the instance even in the rest of the code. + +Virtual lists and dicts +------------------------- + +The examples of `virtual structures`_ seen so far are about virtualizing +objects like instances of RPython classes, which have a ``GcStruct`` +low-level type, i.e. a kind of C ``struct``. The same idea can be +generalized to objects with other kinds of low-level representations; we +call the result *virtual containers*. Beside structures, there are two +further kinds of virtual containers: *virtual lists* and *virtual +dicts*. The idea is the optimize the following kind of code:: + + lst = [] + lst.append(somevalue) + ... + print lst.pop() + +As in the examples of `virtual structures`_, the list manipulations here +produce no residual code whatsoever. At compile-time the ``lst`` +variable is a PtrRedBox referencing a *virtual list* object. A virtual +list is implemented as a list of red boxes: operations like +``append(x)`` just append the red box of ``x`` to the virtual list. The +virtual list must be forced in situations where the shape of the list +can no longer be known at compile-time, e.g. when inserting an element +at an index which is not a compile-time constant. + +Virtual dicts are similar, but only support compile-time constants as +keys (otherwise, we would not know at compile-time whether two run-time +keys are equal or not). They are useful in situations where we build +small dicts with fixed keys; in the PyPy interpreter for example we +foresee that they will be useful to implement the dictionary of +application-level objects, which typically have a few well-known string +keys (the instance's attributes). + +Note that some care is required when timeshifting low-level code that +handles lists and dicts: operations like ``lst.append(x)`` have already +been turned into calls to low-level helpers that manipulate low-level +structures and arrays. If no care is taken, the timeshifter will +consider this as code that handles structures and arrays, and try to +make them virtual structures and (yet unsupported) virtual arrays. +However, this is a bit too low-level: e.g. lists that should be similar +may have accidentally different structures, because of the details of +the over-allocation logic in the low-level helpers. The situation is +even worse for dictionaries, where the details of the key placement in +the hash table is irrelevant at the RPython level but is likely to +confuse the merge logic when trying to compare two virtual dicts. The +timeshifter avoids these issues by special-casing the helpers for lists +and dicts and mapping them to compile-time operations on virtual lists +and virtual dicts. (This is the purpose of the ``oopspec`` annotation +found in the source code of these helpers; as e.g. in +`rpython/rlist.py`_.) + Exceptions ------------ -... +The graphs that the timeshifter inputs are RPython code. As such, they +typically use exceptions. They must be handled in a specific way - the +timeshifted graph itself cannot simply raise and catch the same +exceptions at the same places, because most of these exceptions will +only occur at run-time under some conditions. + +The solution we picked is to *exception-transform* the input graphs +before they are timeshifted. The `exception transformer`_ is a module +that is normally used to prepare a graph for being turned into C code, +by removing the exception handling implicit at the graph level and +turning it into a form suitable for C. This transformation introduces a +*global exception state* structure that stores the current exception +object, if any; it turns exception raising into writing into the global +exception state, and it adds checks in each graph after each operation +that could potentially raise. + +Now, as the timeshifter takes exception-transformed graphs as input, it +would do the right thing without special support. Indeed, loads from +and stores to the global exception state are regular red operations, so +they are simply generated into the residual code. In this model, the +generated residual code would simply check for exception as often as +the original, non-timeshifted graphs did. + +The result is not efficient, however, because many original operations +were removed - for example, green operations are no longer present, and +calls are inlined. This means that the residual graph contains +unnecessary repeated checks. To solve this, we made the global +exception state structure virtual in some sense. The compile-time state +contains two red boxes that correspond to the current exception type and +instance; the intent is that they describe run-time values which +together are considered as the current exception by the residual code. +In other words, when the residual code is itself running, the global +exception state structure is not really containing the current +exception; instead, it is in regular local variables (if the red boxes +are run-time) or simply known as constants at this point (if the red +boxes are compile-time). + +To implement this, the timeshifter needs to special-case the following +places: + +* Operations in the input graphs that directly read from or store to the + global exception state structure become compile-time copies from or to + the compile-time exception red boxes. For example, when the input, + exception-transformed graph wants to clear the current exception, it + stores zeroes in the global exception state; the timeshifter + transforms these into putting red boxes with compile-time zeroes as + the compile-time exception red boxes. Afterwards, any compile-time + code that checks if an exception is set would find the compile-time + zeroes and know that there isn't any. + +* Residual operations that can indirectly raise, like residual calls, + would store an exception into the global exception state; so at + compile-time, just after we generate such a residual operation, we + also generate a pair of ``getfield`` operations that load the run-time + exception back into local run-time variables. This produces + non-constant red boxes which are used as the compile-time exception + boxes. + +* At the end of a residual function, just before returning to the + run-time caller, we generate code that copies the exception boxes back + into the global exception state. + +With the above rules, we can match direct raises with their +corresponding exception handlers purely at compile-time. Indeed, +consider a graph that explicit raises some exception. The exception +transformer first turns it into setting a constant type pointer into the +global exception state. Then the timeshifter turns that code into +storing a constant red box into the compile-time exception state. The +exception remains a compile-time constant until it is either used +(allowing the matching code inserted by the exception transformer to +give compile-time constant answers) or it escapes out of the residual +code (and only in the latter case will residual code store it into the +global exception state for the benefit of the run-time caller). + .. _promotion: @@ -634,16 +826,19 @@ ...global merge point... + Partial data ------------- ... + Portals ---------------------- ... + Scaling to PyPy ---------------------- @@ -674,5 +869,6 @@ .. _`specialization of functions`: dynamic-language-translation.html#specialization .. _Psyco: http://psyco.sourceforge.net .. _`PyPy Standard Interpreter`: architecture.html#standard-interpreter +.. _`exception transformer`: translation.html#making-exception-handling-explicit .. include:: _ref.txt From ericvrp at codespeak.net Sat Dec 23 09:41:21 2006 From: ericvrp at codespeak.net (ericvrp at codespeak.net) Date: Sat, 23 Dec 2006 09:41:21 +0100 (CET) Subject: [pypy-svn] r35964 - in pypy/dist/pypy/jit/codegen/llvm: . test Message-ID: <20061223084121.0AEA21007F@code0.codespeak.net> Author: ericvrp Date: Sat Dec 23 09:41:15 2006 New Revision: 35964 Modified: pypy/dist/pypy/jit/codegen/llvm/rgenop.py pypy/dist/pypy/jit/codegen/llvm/test/test_genc_ts.py pypy/dist/pypy/jit/codegen/llvm/test/test_operation.py pypy/dist/pypy/jit/codegen/llvm/test/test_rgenop.py Log: Skip some codegen/llvm tests when the llvm version < 2.0 Modified: pypy/dist/pypy/jit/codegen/llvm/rgenop.py ============================================================================== --- pypy/dist/pypy/jit/codegen/llvm/rgenop.py (original) +++ pypy/dist/pypy/jit/codegen/llvm/rgenop.py Sat Dec 23 09:41:15 2006 @@ -6,10 +6,9 @@ from pypy.jit.codegen.llvm import llvmjit from pypy.rlib.objectmodel import we_are_translated from pypy.jit.codegen.i386.rgenop import gc_malloc_fnaddr - - from pypy.jit.codegen.llvm.conftest import option + LINENO = option.lineno PRINT_SOURCE = option.print_source PRINT_DEBUG = option.print_debug @@ -17,6 +16,15 @@ WORD = 4 +MINIMAL_VERSION = 2.0 + +def llvm_version(): + v = os.popen('llvm-as -version 2>&1').read() + v = ''.join([c for c in v if c.isdigit()]) + v = int(v) / 10.0 + return v + + class Logger: enabled = True 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 Sat Dec 23 09:41:15 2006 @@ -1,7 +1,7 @@ import py from pypy.jit.codegen.i386.test.test_genc_ts import I386TimeshiftingTestMixin from pypy.jit.timeshifter.test import test_timeshift -from pypy.jit.codegen.llvm.rgenop import RLLVMGenOp +from pypy.jit.codegen.llvm.rgenop import RLLVMGenOp, llvm_version, MINIMAL_VERSION skip_passing = False @@ -21,6 +21,22 @@ def skip(self): py.test.skip("WIP") + def skip_too_minimal(self): + py.test.skip('found llvm %.1f, requires at least llvm %.1f(cvs)' % ( + llvm_version(), MINIMAL_VERSION)) + + if llvm_version() < MINIMAL_VERSION: + test_loop_merging = skip_too_minimal + test_two_loops_merging = skip_too_minimal + test_merge_3_redconsts_before_return = skip_too_minimal + test_degenerated_before_return = skip_too_minimal + test_degenerated_before_return_2 = skip_too_minimal + test_setarrayitem = skip_too_minimal + test_degenerated_via_substructure = skip_too_minimal + test_merge_structures = skip_too_minimal + test_split_on_green_return = skip_too_minimal + test_normalize_indirect_call_more = skip_too_minimal + if skip_passing: test_very_simple = skip test_convert_const_to_redbox = skip Modified: pypy/dist/pypy/jit/codegen/llvm/test/test_operation.py ============================================================================== --- pypy/dist/pypy/jit/codegen/llvm/test/test_operation.py (original) +++ pypy/dist/pypy/jit/codegen/llvm/test/test_operation.py Sat Dec 23 09:41:15 2006 @@ -1,10 +1,7 @@ import py from pypy.jit.codegen.llvm.test.test_llvmjit import skip_unsupported_platform from pypy.jit.codegen.i386.test.test_operation import BasicTests -from pypy.jit.codegen.llvm.rgenop import RLLVMGenOp - - -#skip_unsupported_platform() +from pypy.jit.codegen.llvm.rgenop import RLLVMGenOp, llvm_version, MINIMAL_VERSION class LLVMTestBasicMixin(object): @@ -20,6 +17,20 @@ def skip(self): py.test.skip('WIP') + def skip_too_minimal(self): + py.test.skip('found llvm %.1f, requires at least llvm %.1f(cvs)' % ( + llvm_version(), MINIMAL_VERSION)) + + if llvm_version() < MINIMAL_VERSION: + test_arithmetic = skip_too_minimal + test_comparison = skip_too_minimal + test_char_comparison = skip_too_minimal + test_unichar_comparison = skip_too_minimal + test_char_array = skip_too_minimal + test_char_varsize_array = skip_too_minimal + test_unsigned = skip_too_minimal + test_float_arithmetic = skip_too_minimal + test_float_pow = skip test_unichar_array = skip test_char_unichar_fields = skip Modified: pypy/dist/pypy/jit/codegen/llvm/test/test_rgenop.py ============================================================================== --- pypy/dist/pypy/jit/codegen/llvm/test/test_rgenop.py (original) +++ pypy/dist/pypy/jit/codegen/llvm/test/test_rgenop.py Sat Dec 23 09:41:15 2006 @@ -1,5 +1,5 @@ import py -from pypy.jit.codegen.llvm.rgenop import RLLVMGenOp +from pypy.jit.codegen.llvm.rgenop import RLLVMGenOp, llvm_version, MINIMAL_VERSION from pypy.jit.codegen.test.rgenop_tests import AbstractRGenOpTests from sys import platform @@ -14,4 +14,13 @@ def skip(self): py.test.skip('WIP') + def skip_too_minimal(self): + py.test.skip('found llvm %.1f, requires at least llvm %.1f(cvs)' % ( + llvm_version(), MINIMAL_VERSION)) + + if llvm_version() < MINIMAL_VERSION: + test_goto_direct = skip_too_minimal + test_goto_compile = skip_too_minimal + test_fact_direct = skip_too_minimal + test_fact_compile = skip #XXX Blocked block, introducted by this checkin (I don't understand) From antocuni at codespeak.net Sat Dec 23 11:34:21 2006 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Sat, 23 Dec 2006 11:34:21 +0100 (CET) Subject: [pypy-svn] r35965 - in pypy/dist/pypy/translator/backendopt: . test Message-ID: <20061223103421.7CA421007F@code0.codespeak.net> Author: antocuni Date: Sat Dec 23 11:34:19 2006 New Revision: 35965 Modified: pypy/dist/pypy/translator/backendopt/inline.py pypy/dist/pypy/translator/backendopt/test/test_inline.py Log: - generate keepalive only for lltypesystem - do not longer skip a test that passes - two new failing tests Modified: pypy/dist/pypy/translator/backendopt/inline.py ============================================================================== --- pypy/dist/pypy/translator/backendopt/inline.py (original) +++ pypy/dist/pypy/translator/backendopt/inline.py Sat Dec 23 11:34:19 2006 @@ -13,7 +13,7 @@ from pypy.rpython import rmodel from pypy.tool.algo import sparsemat from pypy.translator.backendopt.support import log, split_block_with_keepalive -from pypy.translator.backendopt.support import generate_keepalive, find_backedges, find_loop_blocks +from pypy.translator.backendopt.support import find_backedges, find_loop_blocks from pypy.translator.backendopt.canraise import RaiseAnalyzer BASE_INLINE_THRESHOLD = 32.4 # just enough to inline add__Int_Int() @@ -223,7 +223,14 @@ if var not in self.varmap: self.varmap[var] = copyvar(None, var) return self.varmap[var] - + + def generate_keepalive(self, *args): + from pypy.translator.backendopt.support import generate_keepalive + if self.translator.rtyper.type_system.name == 'lltypesystem': + return generate_keepalive(*args) + else: + return [] + def passon_vars(self, cache_key): if cache_key in self._passon_vars: return self._passon_vars[cache_key] @@ -331,7 +338,7 @@ for exceptionlink in afterblock.exits[1:]: if exc_match(vtable, exceptionlink.llexitcase): passon_vars = self.passon_vars(link.prevblock) - copiedblock.operations += generate_keepalive(passon_vars) + copiedblock.operations += self.generate_keepalive(passon_vars) copiedlink.target = exceptionlink.target linkargs = self.find_args_in_exceptional_case( exceptionlink, link.prevblock, var_etype, var_evalue, afterblock, passon_vars) @@ -379,7 +386,7 @@ del blocks[-1].exits[0].llexitcase linkargs = copiedexceptblock.inputargs copiedexceptblock.recloseblock(Link(linkargs, blocks[0])) - copiedexceptblock.operations += generate_keepalive(linkargs) + copiedexceptblock.operations += self.generate_keepalive(linkargs) def do_inline(self, block, index_operation): Modified: pypy/dist/pypy/translator/backendopt/test/test_inline.py ============================================================================== --- pypy/dist/pypy/translator/backendopt/test/test_inline.py (original) +++ pypy/dist/pypy/translator/backendopt/test/test_inline.py Sat Dec 23 11:34:19 2006 @@ -486,13 +486,12 @@ assert round(res, 5) == round(32.333333333, 5) def test_indirect_call_with_exception(self): - self._skip_oo('exception rewiring') class Dummy: pass def x1(): return Dummy() # can raise MemoryError def x2(): - return 2 + return None def x3(x): if x: f = x1 @@ -509,6 +508,25 @@ assert x4() == 1 py.test.raises(CannotInline, self.check_inline, x3, x4, []) + +class TestInlineLLType(LLRtypeMixin, BaseTestInline): + + def test_correct_keepalive_placement(self): + def h(x): + if not x: + raise ValueError + return 1 + def f(x): + s = "a %s" % (x, ) + try: + h(len(s)) + except ValueError: + pass + return -42 + eval_func, t = self.check_auto_inlining(f, [int]) + res = eval_func([42]) + assert res == -42 + def test_keepalive_hard_case(self): from pypy.rpython.lltypesystem import lltype Y = lltype.Struct('y', ('n', lltype.Signed)) @@ -529,25 +547,40 @@ res = eval_func([]) assert res == 5 - def test_correct_keepalive_placement(self): - def h(x): - if not x: - raise ValueError - return 1 - def f(x): - s = "a %s" % (x, ) - try: - h(len(s)) - except ValueError: - pass - return -42 - eval_func, t = self.check_auto_inlining(f, [int]) - res = eval_func([42]) - assert res == -42 +class TestInlineOOType(OORtypeMixin, BaseTestInline): + def test_invalid_iterator(self): + py.test.skip('Fixme!') + def f(): + try: + d = {'a': 1, 'b': 2} + for key in d: + d[key] = 0 + return True + except RuntimeError: + return False + eval_func, t = self.check_auto_inlining(f, []) + res = eval_func([]) + assert res == False -class TestInlineLLType(LLRtypeMixin, BaseTestInline): - pass + def test_rtype_r_dict_exceptions(self): + py.test.skip('Fixme!') + from pypy.rlib.objectmodel import r_dict + def raising_hash(obj): + if obj.startswith("bla"): + raise TypeError + return 1 + def eq(obj1, obj2): + return obj1 is obj2 + def f(): + d1 = r_dict(eq, raising_hash) + d1['xxx'] = 1 + try: + x = d1["blabla"] + except Exception: + return 42 + return x -class TestInlineOOType(OORtypeMixin, BaseTestInline): - pass + eval_func, t = self.check_auto_inlining(f, []) + res = eval_func([]) + assert res == 42 From guido at codespeak.net Sat Dec 23 14:22:43 2006 From: guido at codespeak.net (guido at codespeak.net) Date: Sat, 23 Dec 2006 14:22:43 +0100 (CET) Subject: [pypy-svn] r35966 - pypy/dist/pypy/translator/js/doc Message-ID: <20061223132243.20CCA1007F@code0.codespeak.net> Author: guido Date: Sat Dec 23 14:22:41 2006 New Revision: 35966 Added: pypy/dist/pypy/translator/js/doc/webapps_with_pypy.txt Log: Start of a document describing how PyPy can be used to develop web applications easier (describes RPython 2 JavaScript and commproxy). Added: pypy/dist/pypy/translator/js/doc/webapps_with_pypy.txt ============================================================================== --- (empty file) +++ pypy/dist/pypy/translator/js/doc/webapps_with_pypy.txt Sat Dec 23 14:22:41 2006 @@ -0,0 +1,89 @@ +====================================== +Developing web applications with PyPy +====================================== + +What is this (and why)? +------------------------ + +PyPy is a platform that is very versatile, and provides almost endless +possibilities. One of the features that is currently already available is +that of translating RPython (the 'restricted Python' subset) to JavaScript. +This specific feature can make the life of a developer of web applications that +use client-side logic a lot easier, although there are certain hurdles to take. + +Currently the state of the JavaScript backend support for PyPy is usable, but +somewhat complex to use out-of-the-box and not very well documented. I'm +writing this document while investigating the possibilities myself, and hope +that it can serve others to relatively quickly dive in, without having to know +too much of anything in the (rather daunting) PyPy codebase besides the useful +bits for web application development. + +PyPy features for web developers +--------------------------------- + +Of course the 'killer feature' of PyPy for web application developers is the +ability to convert somewhat restricted Python code (aka RPython) into +JavaScript code. Unlike other libraries that perform similar functionality, +PyPy really interprets the code, and produces 'lower level' JavaScript code, +so it implements Python core language features like list comprehensions, and +really behaves like Python (it's not Python syntax with JS semantics). + +However, mostly for demonstration purposes, some other interesting code is +available in the PyPy code package that may help developing web apps. The most +interesting of these I think is a library that transparently makes server-side +functionality available to client-side code, using XMLHttpRequest. This code +lives in a module in pypy/translator/js/examples that's called 'server.py', and +uses a library in pypy/translator/js called 'commproxy.py'. + +Note that the 'server.py' library currently is usable, but not complete: I +assume there will be quite some development and refinement later. This may mean +that certain things in this document are outdated. + +Layers +------- + +As seems to be common in PyPy, web applications will be relatively 'layered': +there are a large number of different 'levels' of code execution. This makes +that writing and debugging web applications written in this manner can be +relatively complicated; however, the gains (such as having client-side code +written in Python, and being able to test it on a normal Python interpreter) +hopefully outweigh those complications. + +A quick overview of the (main) layers of code in the application we're going +to write: + + * HTTP server implementation - 'normal' (C-)Python code + + the web server code, the code that handles dealing with the HTTP API and + dispatching to application code is written in 'normal' Python code, and is + executed on the server in a 'normal' Python interpreter (note that this + does _not_ mean that you can not execute this in a PyPy interpreter, as + long as that interpreter has support for the functionality we need (things + like sockets) that should work) + + * Server-side application code - 'normal' and 'described' Python code + + the application code on the server consists of 'internal' code, code that + is called directly from other server-side code ('normal' Python functions), + and 'exposed' code, code that is made available to the client (and has to + be described) + + exposed functions only support common datatypes (ints, strings, lists + of ints, etc.) for arguments and return values, and have to have those + arguments and return values 'described' so that the rtyper system can + discover how they should be exposed, and so that the (transparently used) + XMLHttpRequest handler and JSON serializer know how they should be treated + + * Client-side application code - RPython code + + the application code on the client lives in a seperate module, and must be + RPython code + + this code can call the 'described' Python code from the server, and also + use the normal client-side (browser) APIs + +Writing a simple application +----------------------------- + +XXX hands-on guide to writing guestbook or something + From arigo at codespeak.net Sat Dec 23 15:59:29 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 23 Dec 2006 15:59:29 +0100 (CET) Subject: [pypy-svn] r35967 - pypy/dist/pypy/objspace/std/test Message-ID: <20061223145929.1A0AE1007F@code0.codespeak.net> Author: arigo Date: Sat Dec 23 15:59:22 2006 New Revision: 35967 Modified: pypy/dist/pypy/objspace/std/test/test_dictobject.py Log: Fix a trivial test failure. Modified: pypy/dist/pypy/objspace/std/test/test_dictobject.py ============================================================================== --- pypy/dist/pypy/objspace/std/test/test_dictobject.py (original) +++ pypy/dist/pypy/objspace/std/test/test_dictobject.py Sat Dec 23 15:59:22 2006 @@ -385,6 +385,8 @@ FakeSpace.config.objspace.std = Config() FakeSpace.config.objspace.std.withdictmeasurement = False FakeSpace.config.objspace.std.withsharingdict = False +FakeSpace.config.objspace.opcodes = Config() +FakeSpace.config.objspace.opcodes.CALL_LIKELY_BUILTIN = False from pypy.objspace.std.dictobject import getitem__Dict_ANY, setitem__Dict_ANY_ANY From ericvrp at codespeak.net Sat Dec 23 19:19:44 2006 From: ericvrp at codespeak.net (ericvrp at codespeak.net) Date: Sat, 23 Dec 2006 19:19:44 +0100 (CET) Subject: [pypy-svn] r35968 - in pypy/dist/pypy/jit/codegen/llvm: . test Message-ID: <20061223181944.B6FF61007C@code0.codespeak.net> Author: ericvrp Date: Sat Dec 23 19:19:42 2006 New Revision: 35968 Modified: pypy/dist/pypy/jit/codegen/llvm/rgenop.py pypy/dist/pypy/jit/codegen/llvm/test/test_llvmjit.py Log: More changes to keep up with the llvm 1.9 to 2.0 transition Modified: pypy/dist/pypy/jit/codegen/llvm/rgenop.py ============================================================================== --- pypy/dist/pypy/jit/codegen/llvm/rgenop.py (original) +++ pypy/dist/pypy/jit/codegen/llvm/rgenop.py Sat Dec 23 19:19:42 2006 @@ -9,6 +9,11 @@ from pypy.jit.codegen.llvm.conftest import option +#note: To use this code you'll need llvm 2.0 . At the time of writing that +# version is still somewhere in the future so use cvs head that gets +# closest! Version 2.0 introduces fileformat changes as described here: +# http://nondot.org/sabre/LLVMNotes/TypeSystemChanges.txt + LINENO = option.lineno PRINT_SOURCE = option.print_source PRINT_DEBUG = option.print_debug @@ -92,6 +97,7 @@ def __init__(self, type): self.n = count.n_vars self.type = type + self.signed = type is 'int' or type is 'float' count.n_vars += 1 def operand(self): @@ -125,6 +131,7 @@ class BoolConst(GenericConst): type = 'bool' + signed = False def __init__(self, value): self.value = bool(value) @@ -132,6 +139,7 @@ class CharConst(GenericConst): type = 'ubyte' + signed = False def __init__(self, value): if type(value) is str: @@ -143,6 +151,7 @@ class UniCharConst(GenericConst): type = 'int' + signed = True def __init__(self, value): self.value = unicode(value) @@ -150,6 +159,7 @@ class IntConst(GenericConst): type = 'int' + signed = True def __init__(self, value): self.value = int(value) @@ -164,6 +174,7 @@ class UIntConst(GenericConst): type = 'uint' + signed = False def __init__(self, value): self.value = int(value) @@ -171,6 +182,7 @@ class FloatConst(GenericConst): type = 'float' + signed = True def __init__(self, value): self.value = float(value) @@ -178,6 +190,7 @@ class AddrConst(GenConst): type = 'int*' + signed = False def __init__(self, addr): self.addr = addr @@ -229,8 +242,9 @@ sourcevartypes = [var.type for var in sourcevars] targetvartypes = [var.type for var in self.inputargs] if sourcevartypes != targetvartypes: - logger.dump('sourcevartypes(%s) != targetvartypes(%s)' % ( + logger.dump('assert fails on: sourcevartypes(%s) != targetvartypes(%s)' % ( sourcevartypes, targetvartypes)) + self.rgenop._dump_partial_lines() assert sourcevartypes == targetvartypes # Check if the source block jumps to 'self' from multiple @@ -370,8 +384,10 @@ def op_int_add(self, gv_x, gv_y): return self._rgenop2_generic('add' , gv_x, gv_y) def op_int_sub(self, gv_x, gv_y): return self._rgenop2_generic('sub' , gv_x, gv_y) def op_int_mul(self, gv_x, gv_y): return self._rgenop2_generic('mul' , gv_x, gv_y) - def op_int_floordiv(self, gv_x, gv_y): return self._rgenop2_generic('sdiv', gv_x, gv_y) - def op_int_mod(self, gv_x, gv_y): return self._rgenop2_generic('srem' , gv_x, gv_y) + def op_int_floordiv(self, gv_x, gv_y): + return self._rgenop2_generic('us'[gv_x.signed] + 'div', gv_x, gv_y) + def op_int_mod(self, gv_x, gv_y): + return self._rgenop2_generic('us'[gv_x.signed] + 'rem' , gv_x, gv_y) def op_int_and(self, gv_x, gv_y): return self._rgenop2_generic('and' , gv_x, gv_y) def op_int_or(self, gv_x, gv_y): return self._rgenop2_generic('or' , gv_x, gv_y) def op_int_xor(self, gv_x, gv_y): return self._rgenop2_generic('xor' , gv_x, gv_y) @@ -388,9 +404,8 @@ gv_y_ubyte = Var('ubyte') self.asm.append(' %s=trunc %s to ubyte' % (gv_y_ubyte.operand2(), gv_y.operand())) gv_result = Var(gv_x.type) - #XXX lshr/ashr - self.asm.append(' %s=lshr %s,%s' % ( - gv_result.operand2(), gv_x.operand(), gv_y_ubyte.operand())) + self.asm.append(' %s=%sshr %s,%s' % ( + gv_result.operand2(), 'la'[gv_x.signed], gv_x.operand(), gv_y_ubyte.operand())) return gv_result op_uint_add = op_float_add = op_int_add @@ -407,19 +422,34 @@ def op_float_truediv(self, gv_x, gv_y): return self._rgenop2_generic('fdiv', gv_x, gv_y) def op_float_neg(self, gv_x): return self._rgenop2_generic('sub', FloatConst(0.0), gv_x) - def op_int_lt(self, gv_x, gv_y): return self._rgenop2_generic('setlt', gv_x, gv_y, 'bool') - def op_int_le(self, gv_x, gv_y): return self._rgenop2_generic('setle', gv_x, gv_y, 'bool') - def op_int_eq(self, gv_x, gv_y): return self._rgenop2_generic('seteq', gv_x, gv_y, 'bool') - def op_int_ne(self, gv_x, gv_y): return self._rgenop2_generic('setne', gv_x, gv_y, 'bool') - def op_int_gt(self, gv_x, gv_y): return self._rgenop2_generic('setgt', gv_x, gv_y, 'bool') - def op_int_ge(self, gv_x, gv_y): return self._rgenop2_generic('setge', gv_x, gv_y, 'bool') - - op_char_lt = op_uint_lt = op_float_lt = op_int_lt - op_char_le = op_uint_le = op_float_le = op_int_le - op_char_eq = op_uint_eq = op_float_eq = op_unichar_eq = op_ptr_eq = op_int_eq - op_char_ne = op_uint_ne = op_float_ne = op_unichar_ne = op_ptr_ne = op_int_ne - op_char_gt = op_uint_gt = op_float_gt = op_int_gt - op_char_ge = op_uint_ge = op_float_ge = op_int_ge + def op_int_lt(self, gv_x, gv_y): return self._rgenop2_generic('icmp slt', gv_x, gv_y, 'bool') + def op_int_le(self, gv_x, gv_y): return self._rgenop2_generic('icmp sle', gv_x, gv_y, 'bool') + def op_int_eq(self, gv_x, gv_y): return self._rgenop2_generic('icmp eq' , gv_x, gv_y, 'bool') + def op_int_ne(self, gv_x, gv_y): return self._rgenop2_generic('icmp ne' , gv_x, gv_y, 'bool') + def op_int_gt(self, gv_x, gv_y): return self._rgenop2_generic('icmp sgt', gv_x, gv_y, 'bool') + def op_int_ge(self, gv_x, gv_y): return self._rgenop2_generic('icmp sge', gv_x, gv_y, 'bool') + + def op_uint_lt(self, gv_x, gv_y): return self._rgenop2_generic('icmp ult', gv_x, gv_y, 'bool') + def op_uint_le(self, gv_x, gv_y): return self._rgenop2_generic('icmp ule', gv_x, gv_y, 'bool') + def op_uint_gt(self, gv_x, gv_y): return self._rgenop2_generic('icmp ugt', gv_x, gv_y, 'bool') + def op_uint_ge(self, gv_x, gv_y): return self._rgenop2_generic('icmp uge', gv_x, gv_y, 'bool') + + def op_float_lt(self, gv_x, gv_y): return self._rgenop2_generic('fcmp olt', gv_x, gv_y, 'bool') + def op_float_le(self, gv_x, gv_y): return self._rgenop2_generic('fcmp ole', gv_x, gv_y, 'bool') + def op_float_eq(self, gv_x, gv_y): return self._rgenop2_generic('fcmp oeq', gv_x, gv_y, 'bool') + def op_float_ne(self, gv_x, gv_y): return self._rgenop2_generic('fcmp one', gv_x, gv_y, 'bool') + def op_float_gt(self, gv_x, gv_y): return self._rgenop2_generic('fcmp ogt', gv_x, gv_y, 'bool') + def op_float_ge(self, gv_x, gv_y): return self._rgenop2_generic('fcmp oge', gv_x, gv_y, 'bool') + + op_unichar_eq = op_ptr_eq = op_uint_eq = op_int_eq + op_unichar_ne = op_ptr_ne = op_uint_ne = op_int_ne + + op_char_lt = op_uint_lt + op_char_le = op_uint_le + op_char_eq = op_uint_eq + op_char_ne = op_uint_ne + op_char_gt = op_uint_gt + op_char_ge = op_uint_ge def _rgenop1_generic(self, llvm_opcode, gv_x, restype=None): log('%s Builder._rgenop1_generic %s %s' % ( @@ -438,8 +468,11 @@ gv_comp = Var('bool') gv_abs_pos = Var(gv_x.type) gv_result = Var(gv_x.type) - self.asm.append(' %s=setge %s,%s' % ( - gv_comp.operand2(), gv_x.operand(), nullstr)) + if nullstr is '0': + l = ' %s=icmp sge %s,%s' + else: + l = ' %s=fcmp oge %s,%s' + self.asm.append(l % (gv_comp.operand2(), gv_x.operand(), nullstr)) self.asm.append(' %s=sub %s %s,%s' % ( gv_abs_pos.operand2(), gv_x.type, nullstr, gv_x.operand2())) self.asm.append(' %s=select %s,%s,%s' % ( @@ -577,15 +610,21 @@ def _is_false(self, gv_x, nullstr='0'): log('%s Builder._is_false %s' % (self.block.label, gv_x.operand())) gv_result = Var('bool') - self.asm.append(' %s=seteq %s,%s' % ( - gv_result.operand2(), gv_x.operand(), nullstr)) + if nullstr is '0': + l = ' %s=icmp eq %s,%s' + else: + l = ' %s=fcmp oeq %s,%s' + self.asm.append(l % (gv_result.operand2(), gv_x.operand(), nullstr)) return gv_result def _is_true(self, gv_x, nullstr='0'): log('%s Builder._is_true %s' % (self.block.label, gv_x.operand())) gv_result = Var('bool') - self.asm.append(' %s=setne %s,%s' % ( - gv_result.operand2(), gv_x.operand(), nullstr)) + if nullstr is '0': + l = ' %s=icmp ne %s,%s' + else: + l = ' %s=fcmp one %s,%s' + self.asm.append(l % (gv_result.operand2(), gv_x.operand(), nullstr)) return gv_result op_bool_is_true = op_char_is_true = op_unichar_is_true = op_int_is_true =\ @@ -605,7 +644,8 @@ t = 'ubyte' else: if fieldsize != 2: - logger.dump('fieldsize != [124]') + logger.dump('assert fails on: fieldsize != [124]') + self.rgenop._dump_partial_lines() assert fieldsize == 2 t = 'short' gv_ptr_var = self._as_var(gv_ptr) @@ -618,7 +658,7 @@ return gv_result def genop_setfield(self, (offset, fieldsize), gv_ptr, gv_value): - log('%s Builder.senop_setfield (%d,%d) %s=%s' % ( + log('%s Builder.genop_setfield (%d,%d) %s=%s' % ( self.block.label, offset, fieldsize, gv_ptr.operand(), gv_value.operand())) #if fieldsize == WORD: # gv_result = Var('int') @@ -633,7 +673,7 @@ self.asm.append(' %s=getelementptr %s,int %s' % ( gv_p.operand2(), gv_ptr_var.operand(), offset / fieldsize)) self.asm.append(' store %s,%s' % ( - gv_value.operand2(), gv_p.operand())) + gv_value.operand(), gv_p.operand())) def genop_getsubstruct(self, (offset, fieldsize), gv_ptr): log('%s Builder.genop_getsubstruct (%d,%d) %s' % ( @@ -730,8 +770,8 @@ def genop_malloc_fixedsize(self, size): log('%s Builder.genop_malloc_fixedsize %s' % ( self.block.label, str(size))) - gv_result = Var('ubyte*') - gv_gc_malloc_fnaddr = Var('ubyte* (int)*') + gv_result = Var('ubyte*') #XXX or opaque* ??? + gv_gc_malloc_fnaddr = Var('%s (int)*' % gv_result.type) #XXX or use addGlobalFunctionMapping in libllvmjit.restart() self.asm.append(' %s=inttoptr int %d to %s ;gc_malloc_fnaddr' % ( gv_gc_malloc_fnaddr.operand2(), gc_malloc_fnaddr(), gv_gc_malloc_fnaddr.type)) @@ -742,8 +782,8 @@ def genop_malloc_varsize(self, varsizealloctoken, gv_size): log('%s Builder.genop_malloc_varsize %s,%s' % ( self.block.label, varsizealloctoken, gv_size.operand())) - gv_result = Var('ubyte*') - gv_gc_malloc_fnaddr = Var('ubyte* (int)*') + gv_result = Var('ubyte*') #XXX or opaque* ??? + gv_gc_malloc_fnaddr = Var('%s (int)*' % gv_result.type) #XXX or use addGlobalFunctionMapping in libllvmjit.restart() self.asm.append(' %s=inttoptr int %d to %s ;gc_malloc_fnaddr' % ( gv_gc_malloc_fnaddr.operand2(), gc_malloc_fnaddr(), gv_gc_malloc_fnaddr.type)) @@ -802,6 +842,14 @@ def check_no_open_mc(self): return True + def _dump_partial_lines(self): #what we've generated so far + asmlines = [] + for block in self.blocklist: + block.writecode(asmlines) + asmlines = ['%s ;%d' % (asmlines[i], i+1) for i in range(len(asmlines))] + asm_string = '\n'.join(asmlines) + logger.dump(asm_string) + def end(self): log(' RLLVMGenOp.end') self.blocklist.append(EpilogueBlock()) Modified: pypy/dist/pypy/jit/codegen/llvm/test/test_llvmjit.py ============================================================================== --- pypy/dist/pypy/jit/codegen/llvm/test/test_llvmjit.py (original) +++ pypy/dist/pypy/jit/codegen/llvm/test/test_llvmjit.py Sat Dec 23 19:19:42 2006 @@ -28,7 +28,7 @@ # lldeadcode = '''int %deadcode(int %n) { Test: - %cond = seteq int %n, %n + %cond = icmp eq int %n, %n br bool %cond, label %IfEqual, label %IfUnequal IfEqual: From antocuni at codespeak.net Sun Dec 24 12:27:36 2006 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Sun, 24 Dec 2006 12:27:36 +0100 (CET) Subject: [pypy-svn] r35972 - in pypy/dist/pypy/translator/backendopt: . test Message-ID: <20061224112736.73BB91007A@code0.codespeak.net> Author: antocuni Date: Sun Dec 24 12:27:35 2006 New Revision: 35972 Modified: pypy/dist/pypy/translator/backendopt/inline.py pypy/dist/pypy/translator/backendopt/test/test_inline.py Log: Record all oosend as operations that could raise exceptions. Not sure that it's the best way to do it; probably we will need some analysis that maps each oosend to the set of graphs that could be called. Modified: pypy/dist/pypy/translator/backendopt/inline.py ============================================================================== --- pypy/dist/pypy/translator/backendopt/inline.py (original) +++ pypy/dist/pypy/translator/backendopt/inline.py Sun Dec 24 12:27:35 2006 @@ -39,6 +39,8 @@ else: for graph in graphs: graphs_or_something[graph] = True + if op.opname == 'oosend': + graphs_or_something[op.args[0]] = True # XXX? return graphs_or_something def iter_callsites(graph, calling_what): Modified: pypy/dist/pypy/translator/backendopt/test/test_inline.py ============================================================================== --- pypy/dist/pypy/translator/backendopt/test/test_inline.py (original) +++ pypy/dist/pypy/translator/backendopt/test/test_inline.py Sun Dec 24 12:27:35 2006 @@ -549,22 +549,7 @@ class TestInlineOOType(OORtypeMixin, BaseTestInline): - def test_invalid_iterator(self): - py.test.skip('Fixme!') - def f(): - try: - d = {'a': 1, 'b': 2} - for key in d: - d[key] = 0 - return True - except RuntimeError: - return False - eval_func, t = self.check_auto_inlining(f, []) - res = eval_func([]) - assert res == False - def test_rtype_r_dict_exceptions(self): - py.test.skip('Fixme!') from pypy.rlib.objectmodel import r_dict def raising_hash(obj): if obj.startswith("bla"): @@ -584,3 +569,4 @@ eval_func, t = self.check_auto_inlining(f, []) res = eval_func([]) assert res == 42 + From antocuni at codespeak.net Sun Dec 24 14:27:34 2006 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Sun, 24 Dec 2006 14:27:34 +0100 (CET) Subject: [pypy-svn] r35977 - pypy/dist/pypy/translator/cli Message-ID: <20061224132734.C5A1E10070@code0.codespeak.net> Author: antocuni Date: Sun Dec 24 14:27:33 2006 New Revision: 35977 Modified: pypy/dist/pypy/translator/cli/opcodes.py Log: bugfix. It's incredible how this bug has been hidden until now... Modified: pypy/dist/pypy/translator/cli/opcodes.py ============================================================================== --- pypy/dist/pypy/translator/cli/opcodes.py (original) +++ pypy/dist/pypy/translator/cli/opcodes.py Sun Dec 24 14:27:33 2006 @@ -15,7 +15,7 @@ return [PushAllArgs, op]+Not def _abs(type_): - return [PushAllArgs, 'call %s class [mscorlib]System.Math::Abs(%s)' % (type_, type_)] + return [PushAllArgs, 'call %s class [mscorlib]System.Math::Abs(%s)' % (type_, type_), StoreResult] def _check_ovf(op): mapping = [('[mscorlib]System.OverflowException', 'exceptions.OverflowError')] @@ -166,6 +166,7 @@ 'llong_neg': 'neg', 'llong_neg_ovf': _check_ovf(['ldc.i8 0', PushAllArgs, 'sub.ovf', StoreResult]), 'llong_abs': _abs('int64'), + 'llong_abs_ovf': _check_ovf(_abs('int64')), 'llong_invert': 'not', 'llong_add': 'add', From antocuni at codespeak.net Sun Dec 24 14:32:53 2006 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Sun, 24 Dec 2006 14:32:53 +0100 (CET) Subject: [pypy-svn] r35978 - pypy/dist/pypy/translator/cli/test Message-ID: <20061224133253.D2C5910070@code0.codespeak.net> Author: antocuni Date: Sun Dec 24 14:32:53 2006 New Revision: 35978 Modified: pypy/dist/pypy/translator/cli/test/test_string.py Log: skip this test. Modified: pypy/dist/pypy/translator/cli/test/test_string.py ============================================================================== --- pypy/dist/pypy/translator/cli/test/test_string.py (original) +++ pypy/dist/pypy/translator/cli/test/test_string.py Sun Dec 24 14:32:53 2006 @@ -33,6 +33,9 @@ def test_replace_TyperError(self): pass # it doesn't make sense here + def test_hlstr(self): + py.test.skip("CLI tests can't have string as input arguments") + def test_hash_value(self): # make that hash are computed by value and not by reference def fn(x, y): From antocuni at codespeak.net Sun Dec 24 15:15:03 2006 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Sun, 24 Dec 2006 15:15:03 +0100 (CET) Subject: [pypy-svn] r35979 - pypy/dist/pypy/translator/cli/test Message-ID: <20061224141503.8936310072@code0.codespeak.net> Author: antocuni Date: Sun Dec 24 15:15:02 2006 New Revision: 35979 Modified: pypy/dist/pypy/translator/cli/test/test_dotnet.py Log: Skip these tests when not using native CLI exceptions for RPython exceptions. 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 Sun Dec 24 15:15:02 2006 @@ -118,6 +118,11 @@ def _skip_pythonnet(self, msg): pass + def _skip_exception(self): + from pypy.translator.cli import function + if function.USE_LAST: + py.test.skip("Fixme!") + def test_staticmeth_call(self): def fn(x): return Math.Abs(x) @@ -218,6 +223,7 @@ assert self.interpret(fn, []) is None def test_native_exception_precise(self): + self._skip_exception() ArgumentOutOfRangeException = NativeException(CLR.System.ArgumentOutOfRangeException) def fn(): x = ArrayList() @@ -229,6 +235,7 @@ assert self.interpret(fn, []) == True def test_native_exception_superclass(self): + self._skip_exception() SystemException = NativeException(CLR.System.Exception) def fn(): x = ArrayList() @@ -240,6 +247,7 @@ assert self.interpret(fn, []) == True def test_native_exception_object(self): + self._skip_exception() SystemException = NativeException(CLR.System.Exception) def fn(): x = ArrayList() @@ -253,6 +261,7 @@ assert res.startswith("Index is less than 0") def test_native_exception_invoke(self): + self._skip_exception() TargetInvocationException = NativeException(CLR.System.Reflection.TargetInvocationException) def fn(): x = ArrayList() From santagada at codespeak.net Mon Dec 25 18:55:11 2006 From: santagada at codespeak.net (santagada at codespeak.net) Date: Mon, 25 Dec 2006 18:55:11 +0100 (CET) Subject: [pypy-svn] r35980 - pypy/dist/pypy/lang/js Message-ID: <20061225175511.AEA611007A@code0.codespeak.net> Author: santagada Date: Mon Dec 25 18:55:05 2006 New Revision: 35980 Modified: pypy/dist/pypy/lang/js/interpreter.py pypy/dist/pypy/lang/js/jsobj.py Log: All tests passing :) Lets play with named functions and then prototypes. Modified: pypy/dist/pypy/lang/js/interpreter.py ============================================================================== --- pypy/dist/pypy/lang/js/interpreter.py (original) +++ pypy/dist/pypy/lang/js/interpreter.py Mon Dec 25 18:55:05 2006 @@ -2,6 +2,7 @@ from pypy.lang.js.astgen import * from pypy.lang.js.jsparser import parse from pypy.lang.js.jsobj import * +from pypy.lang.js.reference import Reference def writer(x): print x @@ -45,7 +46,9 @@ class __extend__(Assign): def call(self, ctx): + print "Assign LHS = ", self.LHSExp v1 = self.LHSExp.call(ctx) + print "Assign Exp = ", self.AssignmentExp v3 = self.AssignmentExp.call(ctx).GetValue() v1.PutValue(v3, ctx) return v3 @@ -77,21 +80,21 @@ return self.right.call(ctx) class __extend__(Dot): - def call(self, ctx=None): + def call(self, ctx): w_obj = self.left.call(ctx).GetValue().ToObject() name = self.right.get_literal() - return w_obj.Get(name) + return Reference(name, w_obj) - def put(self, ctx, val): - print self.left.name, self.right.name, val - if isinstance(self.left,Identifier): - obj = ctx.access(self.left.name) - print obj.Class - obj.dict_w[self.right.name] = val - elif isinstance(self.left,Dot): - obj = self.left.put(ctx, val) - - return obj + # def put(self, ctx, val): + # print self.left.name, self.right.name, val + # if isinstance(self.left,Identifier): + # obj = ctx.access(self.left.name) + # print obj.Class + # obj.dict_w[self.right.name] = val + # elif isinstance(self.left,Dot): + # obj = self.left.put(ctx, val) + # + # return obj #w_obj = self.left.put(ctx).GetValue().ToObject() #name = self.right.get_literal() @@ -110,8 +113,8 @@ ref.PutValue(self.initialiser.call(ctx), ctx) return ctx.resolve_identifier(self.name) - def put(self, ctx, val, obj=None): - ctx.assign(self.name, val) + # def put(self, ctx, val, obj=None): + # ctx.assign(self.name, val) def get_literal(self): return self.name Modified: pypy/dist/pypy/lang/js/jsobj.py ============================================================================== --- pypy/dist/pypy/lang/js/jsobj.py (original) +++ pypy/dist/pypy/lang/js/jsobj.py Mon Dec 25 18:55:05 2006 @@ -17,6 +17,9 @@ self.ReadOnly = ReadOnly self.DontEnum = DontEnum self.Internal = Internal + + def __repr__(self): + return "|%s %d%d%d|"%(self.value, self.DontDelete, self.ReadOnly, self.DontEnum) def internal_property(name, value): """return a internal property with the right attributes""" @@ -251,10 +254,6 @@ return w_Undefined -class W_Reference(W_Root): - def GetValue(self): - raise NotImplementedError("W_Reference.GetValue") - class W_Builtin(W_Root): def __init__(self, builtinfunction): #W_Object.__init__(self) From santagada at codespeak.net Mon Dec 25 20:20:03 2006 From: santagada at codespeak.net (santagada at codespeak.net) Date: Mon, 25 Dec 2006 20:20:03 +0100 (CET) Subject: [pypy-svn] r35981 - in pypy/dist/pypy/lang/js: . test Message-ID: <20061225192003.832AA10036@code0.codespeak.net> Author: santagada Date: Mon Dec 25 20:19:57 2006 New Revision: 35981 Removed: pypy/dist/pypy/lang/js/reference.py Modified: pypy/dist/pypy/lang/js/astgen.py pypy/dist/pypy/lang/js/interpreter.py pypy/dist/pypy/lang/js/jsobj.py pypy/dist/pypy/lang/js/test/test_interp.py Log: reference error working and made some tests Modified: pypy/dist/pypy/lang/js/astgen.py ============================================================================== --- pypy/dist/pypy/lang/js/astgen.py (original) +++ pypy/dist/pypy/lang/js/astgen.py Mon Dec 25 20:19:57 2006 @@ -140,7 +140,6 @@ class Vars(Node): def __init__(self, nodes): self.nodes = nodes - #[scope_manager.add_variable(id.name, w_Undefined) for id in nodes] class While(Node): def __init__(self, condition, body): Modified: pypy/dist/pypy/lang/js/interpreter.py ============================================================================== --- pypy/dist/pypy/lang/js/interpreter.py (original) +++ pypy/dist/pypy/lang/js/interpreter.py Mon Dec 25 20:19:57 2006 @@ -2,20 +2,10 @@ from pypy.lang.js.astgen import * from pypy.lang.js.jsparser import parse from pypy.lang.js.jsobj import * -from pypy.lang.js.reference import Reference def writer(x): print x -class ExecutionReturned(Exception): - def __init__(self, value): - self.value = value - -class ThrowException(Exception): - def __init__(self, exception): - self.exception = exception - self.args = self.exception - class Interpreter(object): """Creates a js interpreter""" def __init__(self, script_source=None): @@ -84,22 +74,6 @@ w_obj = self.left.call(ctx).GetValue().ToObject() name = self.right.get_literal() return Reference(name, w_obj) - - # def put(self, ctx, val): - # print self.left.name, self.right.name, val - # if isinstance(self.left,Identifier): - # obj = ctx.access(self.left.name) - # print obj.Class - # obj.dict_w[self.right.name] = val - # elif isinstance(self.left,Dot): - # obj = self.left.put(ctx, val) - # - # return obj - - #w_obj = self.left.put(ctx).GetValue().ToObject() - #name = self.right.get_literal() - #w_obj.dict_w[self.name] = val - class __extend__(Function): def call(self, ctx): @@ -112,9 +86,6 @@ ref = ctx.resolve_identifier(self.name) ref.PutValue(self.initialiser.call(ctx), ctx) return ctx.resolve_identifier(self.name) - - # def put(self, ctx, val, obj=None): - # ctx.assign(self.name, val) def get_literal(self): return self.name Modified: pypy/dist/pypy/lang/js/jsobj.py ============================================================================== --- pypy/dist/pypy/lang/js/jsobj.py (original) +++ pypy/dist/pypy/lang/js/jsobj.py Mon Dec 25 20:19:57 2006 @@ -1,10 +1,19 @@ # encoding: utf-8 -from pypy.lang.js.reference import Reference class SeePage(NotImplementedError): pass +class ExecutionReturned(Exception): + def __init__(self, value): + self.value = value + +class ThrowException(Exception): + def __init__(self, exception): + self.exception = exception + self.args = self.exception + + INFDEF = 1e300 * 1e300 NaN = INFDEF/INFDEF @@ -183,7 +192,7 @@ class W_Undefined(W_Root): def __str__(self): - return "" + return "w_undefined" def ToNumber(self): # XXX make NaN @@ -191,6 +200,9 @@ def ToBoolean(self): return False + + def ToString(self): + return "undefined" class W_Null(W_Root): def __str__(self): @@ -340,4 +352,30 @@ ctx.property = Property('', w_Undefined) return ctx - \ No newline at end of file +class Reference(object): + """Reference Type""" + def __init__(self, property_name, base=None): + self.base = base + self.property_name = property_name + + def GetValue(self): + if self.base is None: + exception = "ReferenceError: %s is not defined"%(self.property_name,) + raise ThrowException(W_String(exception)) + return self.base.Get(self.property_name) + + def PutValue(self, w, ctx): + base = self.base + if self.base is None: + base = ctx.scope[-1] + base.Put(self.property_name, w) + + def GetBase(self): + return self.base + + def GetPropertyName(self): + return self.property_name + + def __str__(self): + return "< " + str(self.base) + " -> " + str(self.property_name) + " >" + \ No newline at end of file Modified: pypy/dist/pypy/lang/js/test/test_interp.py ============================================================================== --- pypy/dist/pypy/lang/js/test/test_interp.py (original) +++ pypy/dist/pypy/lang/js/test/test_interp.py Mon Dec 25 20:19:57 2006 @@ -22,8 +22,6 @@ class TestInterp(object): def test_simple(self): assert Plus(Number(3), Number(4)).call(ExecutionContext()).floatval == 7 - # s = Script([Semicolon(Plus(Number(3), Number(4)))], [], []) - # s.call() l = [] interpreter.writer = l.append Script([Semicolon(Call(Identifier('print', None), @@ -68,7 +66,7 @@ def test_object_access(self): self.assert_prints("x={d:3}; print(x.d);", ["3"]) - self.assert_prints("x={d:3}; print(x.d.d);", [""]) + self.assert_prints("x={d:3}; print(x.d.d);", ["undefined"]) self.assert_prints("x={d:3, z:4}; print(x.d+x.z);", ["7"]) def test_object_access_index(self): @@ -233,8 +231,18 @@ print(o); """, ["[object Object]"]) + def test_var_decl(self): + self.assert_prints("print(x); var x;", ["undefined"]) + self.assert_prints(""" + try { + print(z); + } + catch (e) { + print(e) + } + """, ["ReferenceError: z is not defined"]) + def test_function_name(self): - py.test.skip("not ready yet") self.assert_prints(""" function x() { print("my name is x"); From santagada at codespeak.net Mon Dec 25 20:44:05 2006 From: santagada at codespeak.net (santagada at codespeak.net) Date: Mon, 25 Dec 2006 20:44:05 +0100 (CET) Subject: [pypy-svn] r35982 - pypy/dist/pypy/lang/js Message-ID: <20061225194405.D94251007E@code0.codespeak.net> Author: santagada Date: Mon Dec 25 20:44:01 2006 New Revision: 35982 Modified: pypy/dist/pypy/lang/js/astgen.py pypy/dist/pypy/lang/js/interpreter.py Log: named functions Modified: pypy/dist/pypy/lang/js/astgen.py ============================================================================== --- pypy/dist/pypy/lang/js/astgen.py (original) +++ pypy/dist/pypy/lang/js/astgen.py Mon Dec 25 20:44:01 2006 @@ -232,7 +232,6 @@ elif tp == 'RETURN': return Return(from_dict(d['value'])) elif tp == 'SCRIPT': - # TODO: get function names if isinstance(d['funDecls'], dict): func_decl = [from_dict(d['funDecls']),] else: Modified: pypy/dist/pypy/lang/js/interpreter.py ============================================================================== --- pypy/dist/pypy/lang/js/interpreter.py (original) +++ pypy/dist/pypy/lang/js/interpreter.py Mon Dec 25 20:44:01 2006 @@ -209,6 +209,9 @@ def call(self, ctx): for var in self.var_decl: ctx.variable.Put(var.name, w_Undefined) + for fun in self.func_decl: + ctx.variable.Put(fun.name, fun.call(ctx)) + try: last = w_Undefined From cfbolz at codespeak.net Tue Dec 26 18:24:58 2006 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Tue, 26 Dec 2006 18:24:58 +0100 (CET) Subject: [pypy-svn] r35987 - in pypy/dist/pypy/module/bz2: . test Message-ID: <20061226172458.AA5231007A@code0.codespeak.net> Author: cfbolz Date: Tue Dec 26 18:24:57 2006 New Revision: 35987 Removed: pypy/dist/pypy/module/bz2/fileobject.py Modified: pypy/dist/pypy/module/bz2/__init__.py pypy/dist/pypy/module/bz2/app_bz2.py pypy/dist/pypy/module/bz2/interp_bz2.py pypy/dist/pypy/module/bz2/test/test_bz2_file.py Log: this years christmas present takes lines of code away: base bz2 on rlib/streamio.py. This allows the removal of several hundred lines of code! now bz2.BZ2File is a subclass of file and behaves very similarly. I don't know whether bz2 is translatable now, but it has a much better chance (since it is no longer using anything of CPython's API) Modified: pypy/dist/pypy/module/bz2/__init__.py ============================================================================== --- pypy/dist/pypy/module/bz2/__init__.py (original) +++ pypy/dist/pypy/module/bz2/__init__.py Tue Dec 26 18:24:57 2006 @@ -3,13 +3,14 @@ class Module(MixedModule): interpleveldefs = { - 'BZ2File': 'interp_bz2.BZ2File', - 'BZ2Compressor': 'interp_bz2.BZ2Compressor', - 'BZ2Decompressor': 'interp_bz2.BZ2Decompressor', + 'BZ2Compressor': 'interp_bz2.W_BZ2Compressor', + 'BZ2Decompressor': 'interp_bz2.W_BZ2Decompressor', 'compress': 'interp_bz2.compress', 'decompress': 'interp_bz2.decompress', + '_open_file_as_stream': 'interp_bz2.open_file_as_stream' } appleveldefs = { - '__doc__': 'app_bz2.__doc__' + '__doc__': 'app_bz2.__doc__', + 'BZ2File': 'app_bz2.BZ2File', } Modified: pypy/dist/pypy/module/bz2/app_bz2.py ============================================================================== --- pypy/dist/pypy/module/bz2/app_bz2.py (original) +++ pypy/dist/pypy/module/bz2/app_bz2.py Tue Dec 26 18:24:57 2006 @@ -2,3 +2,45 @@ the bz2 compression library. It implements a complete file interface, one shot (de)compression functions, and types for sequential (de)compression.""" + + +class BZ2File(file): + """BZ2File(name [, mode='r', buffering=0, compresslevel=9]) -> file object + + Open a bz2 file. The mode can be 'r' or 'w', for reading (default) or + writing. When opened for writing, the file will be created if it doesn't + exist, and truncated otherwise. If the buffering argument is given, 0 means + unbuffered, and larger numbers specify the buffer size. If compresslevel + is given, must be a number between 1 and 9. + + Add a 'U' to mode to open the file for input with universal newline + support. Any line ending in the input file will be seen as a '\\n' in + Python. Also, a file so opened gains the attribute 'newlines'; the value + for this attribute is one of None (no newline read yet), '\\r', '\\n', + '\\r\\n' or a tuple containing all the newline types seen. Universal + newlines are available only when reading.""" + def __init__(self, name, mode='r', buffering=-1, compresslevel=9): + import bz2 + # the stream should always be opened in binary mode + if "b" not in mode: + mode = mode + "b" + self._name = name + self.softspace = 0 # Required according to file object docs + self.encoding = None # This is not used internally by file objects + self._closed = False + self.stream = bz2._open_file_as_stream(self._name, mode, buffering, + compresslevel) + self._mode = mode + self.fd = self.stream.try_to_find_file_descriptor() + assert self.fd != -1 + + def fdopen(cls, fd, mode='r', buffering=-1): + raise TypeError("fdopen not supported by BZ2File") + fdopen = classmethod(fdopen) + + def __repr__(self): + return '<%s bz2.BZ2File %r, mode %r at 0x%x>' % ( + self._closed and 'closed' or 'open', + self._name, + self._mode, + id(self)) 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 Dec 26 18:24:57 2006 @@ -1,18 +1,16 @@ from pypy.rpython.rctypes.tool import ctypes_platform -from pypy.rpython.rctypes.tool.libc import libc import pypy.rpython.rctypes.implementation # this defines rctypes magic -from pypy.rpython.rctypes.aerrno import geterrno from pypy.interpreter.error import OperationError -from pypy.interpreter.baseobjspace import W_Root, ObjSpace, Wrappable +from pypy.interpreter.baseobjspace import Wrappable from pypy.interpreter.typedef import TypeDef, GetSetProperty from pypy.interpreter.typedef import interp_attrproperty -from pypy.interpreter.gateway import interp2app +from pypy.interpreter.gateway import ObjSpace, W_Root, NoneNotWrapped, interp2app +from pypy.rlib.streamio import Stream from ctypes import * import ctypes.util import sys from bzlib import bz_stream, BZFILE, FILE -from fileobject import PyFileObject libbz2 = cdll.LoadLibrary(ctypes.util.find_library("bz2")) @@ -65,18 +63,6 @@ BZ_UNEXPECTED_EOF = cConfig.BZ_UNEXPECTED_EOF BZ_SEQUENCE_ERROR = cConfig.BZ_SEQUENCE_ERROR -# modes -MODE_CLOSED = 0 -MODE_READ = 1 -MODE_READ_EOF = 2 -MODE_WRITE = 3 - -# bits in f_newlinetypes -NEWLINE_UNKNOWN = 0 # No newline seen, yet -NEWLINE_CR = 1 # \r newline seen -NEWLINE_LF = 2 # \n newline seen -NEWLINE_CRLF = 4 # \r\n newline seen - if BUFSIZ < 8192: SMALLCHUNK = 8192 else: @@ -100,17 +86,8 @@ def _bzs_total_out(bzs): return bzs.total_out -pythonapi.PyFile_FromString.argtypes = [c_char_p, c_char_p] -pythonapi.PyFile_FromString.restype = POINTER(PyFileObject) -pythonapi.PyFile_SetBufSize.argtypes = [POINTER(PyFileObject), c_int] -pythonapi.PyFile_SetBufSize.restype = c_void -pythonapi.PyFile_AsFile.argtypes = [POINTER(PyFileObject)] -pythonapi.PyFile_AsFile.restype = POINTER(FILE) -pythonapi.PyMem_Free.argtypes = [c_char_p] -pythonapi.PyMem_Free.restype = c_void - # the least but one parameter should be c_void_p but it's not used -# so I trick the compiler to not complaint about constanst pointer passed +# so I trick the compiler to not complain about constanst pointer passed # to void* arg libbz2.BZ2_bzReadOpen.argtypes = [POINTER(c_int), POINTER(FILE), c_int, c_int, POINTER(c_int), c_int] @@ -142,17 +119,6 @@ libbz2.BZ2_bzDecompress.argtypes = [POINTER(bz_stream)] libbz2.BZ2_bzDecompress.restype = c_int -libc.strerror.restype = c_char_p -libc.strerror.argtypes = [c_int] -libc.fclose.argtypes = [POINTER(FILE)] -libc.fclose.restype = c_int -libc.fseek.argtypes = [POINTER(FILE), c_int, c_int] -libc.fseek.restype = c_int - -def _get_error_msg(): - errno = geterrno() - return libc.strerror(errno) - def _catch_bz2_error(space, bzerror): if BZ_CONFIG_ERROR and bzerror == BZ_CONFIG_ERROR: raise OperationError(space.w_SystemError, @@ -174,171 +140,6 @@ raise OperationError(space.w_RuntimeError, space.wrap("wrong sequence of bz2 library commands used")) -def _drop_readahead(obj): - if obj.f_buf: - pythonapi.PyMem_Free(obj.f_buf) - obj.f_buf = c_char_p() - -def _univ_newline_read(bzerror, stream, buf, n, obj): - dst = buf - - if not obj.f_univ_newline: - buf_p = cast(buf, POINTER(c_char)) - nread = libbz2.BZ2_bzRead(byref(bzerror), stream, buf_p, n) - return nread, buf - - newlinetypes = obj.f_newlinetypes - skipnextlf = obj.f_skipnextlf - - dst_lst = [] - src_pos = dst_pos = 0 - while n: - src = dst - - buf_p = cast(buf, POINTER(c_char)) - nread = libbz2.BZ2_bzRead(byref(bzerror), stream, buf_p, n) - n -= nread # assuming 1 byte out for each in; will adjust - shortread = n != 0 # True iff EOF or error - - # needed to operate with "pointers" - src_lst = [c for c in src.value] - src_pos = 0 - dst_lst = [c for c in dst.value] - dst_pos = 0 - while nread: - nread -= 1 - - c = src_lst[src_pos] - src_pos += 1 - - if c == '\r': - # save as LF and set flag to skip next LF. - dst_lst[dst_pos] = '\n' - dst_pos += 1 - skipnextlf = True - elif skipnextlf and c == '\n': - # skip LF, and remember we saw CR LF. - skipnextlf = False - newlinetypes |= NEWLINE_CRLF - n += 1 - else: - # normal char to be stored in buffer. Also - # update the newlinetypes flag if either this - # is an LF or the previous char was a CR. - if c == '\n': - newlinetypes |= NEWLINE_LF - elif skipnextlf: - newlinetypes |= NEWLINE_CR - - dst_lst[dst_pos] = c - dst_pos += 1 - - skipnextlf = False - - if shortread: - # if this is EOF, update type flags. - if skipnextlf and (bzerror.value == BZ_STREAM_END): - newlinetypes |= NEWLINE_CR - break - - obj.f_newlinetypes = newlinetypes - obj.f_skipnextlf = skipnextlf - - data = "".join(dst_lst) - buf = create_string_buffer(len(data)) - for i in range(len(data)): - buf[i] = data[i] - - return dst_pos, buf - -def _getline(space, obj, size): - used_v_size = 0 # no. used slots in buffer - increment = 0 # amount to increment the buffer - bzerror = c_int() - - newlinetypes = obj.f_newlinetypes - skipnextlf = obj.f_skipnextlf - univ_newline = obj.f_univ_newline - - total_v_size = [100, size][size > 0] # total no. of slots in buffer - buf_lst = [] - buf_pos = 0 - - end_pos = buf_pos + total_v_size - - ch = c_char() - while True: - if univ_newline: - while True: - libbz2.BZ2_bzRead(byref(bzerror), obj.fp, byref(ch), 1) - obj.pos += 1 - if bzerror.value != BZ_OK or buf_pos == end_pos: - break - - if skipnextlf: - skipnextlf = False - if ch.value == '\n': - # Seeing a \n here with - # skipnextlf true means we saw a \r before. - newlinetypes |= NEWLINE_CRLF - libbz2.BZ2_bzRead(byref(bzerror), obj.fp, byref(ch), 1) - if bzerror.value != BZ_OK: break - else: - newlinetypes |= NEWLINE_CR - - if ch.value == '\r': - skipnextlf = True - ch.value = '\n' - elif ch.value == '\n': - newlinetypes |= NEWLINE_LF - buf_lst.append(ch.value) - buf_pos += 1 - - if ch.value == '\n': break - if bzerror.value == BZ_STREAM_END and skipnextlf: - newlinetypes |= NEWLINE_CR - else: # if not universal newlines use the normal loop - while True: - libbz2.BZ2_bzRead(byref(bzerror), obj.fp, byref(ch), 1) - obj.pos += 1 - buf_lst.append(ch.value) - buf_pos += 1 - - if not (bzerror.value == BZ_OK and ch.value != '\n' and buf_pos != end_pos): - break - - obj.f_newlinetypes = newlinetypes - obj.f_skipnextlf = skipnextlf - - if bzerror.value == BZ_STREAM_END: - obj.size = obj.pos - obj.mode = MODE_READ_EOF - break - elif bzerror.value != BZ_OK: - _catch_bz2_error(space, bzerror.value) - - if ch.value == '\n': break - # must be because buf_pos == end_pos - if size > 0: - break - - used_v_size = total_v_size - increment = total_v_size >> 2 # mild exponential growth - total_v_size += increment - - if total_v_size > MAXINT: - raise OperationError(space.w_OverflowError, - space.wrap("line is longer than a Python string can hold")) - - buf_pos += used_v_size - end_pos += total_v_size - - used_v_size = buf_pos - if used_v_size != total_v_size: - assert used_v_size >= 0 - return "".join(buf_lst[0:used_v_size]) - return "".join(buf_lst) - def _new_buffer_size(current_size): if current_size > SMALLCHUNK: # keep doubling until we reach BIGCHUNK @@ -348,450 +149,170 @@ else: return current_size + BIGCHUNK return current_size + SMALLCHUNK - -class _BZ2File(Wrappable): - def __init__(self, space, filename, mode='r', buffering=-1, compresslevel=9): + +def open_file_as_stream(space, path, mode="r", buffering=-1, compresslevel=9): + from pypy.rlib.streamio import decode_mode, open_path_helper + from pypy.rlib.streamio import construct_stream_tower + from pypy.module._file.interp_file import wrap_oserror_as_ioerror, W_Stream + from pypy.module._file.interp_file import is_mode_ok + is_mode_ok(space, mode) + os_flags, universal, reading, writing, basemode = decode_mode(mode) + if reading and writing: + raise OperationError(space.w_ValueError, + space.wrap("cannot open in read-write mode")) + if basemode == "a": + raise OperationError(space.w_ValueError, + space.wrap("cannot append to bz2 file")) + try: + stream = open_path_helper(path, os_flags, False) + except OSError, exc: + raise wrap_oserror_as_ioerror(space, exc) + if reading: + bz2stream = ReadBZ2Filter(space, stream, compresslevel) + else: + assert writing + bz2stream = WriteBZ2Filter(space, stream, compresslevel) + stream = construct_stream_tower(bz2stream, buffering, universal, reading, + writing) + return space.wrap(W_Stream(space, stream)) +open_file_as_stream.unwrap_spec = [ObjSpace, str, str, int, int] + + +class ReadBZ2Filter(Stream): + + """Standard I/O stream filter that decompresses the stream with bz2.""" + + def __init__(self, space, stream, compresslevel): self.space = space - - self.f_buf = c_char_p() # allocated readahead buffer - self.f_bufend = c_char_p() # points after last occupied position - self.f_bufptr = c_char_p() # current buffer position - - self.f_softspace = False # flag used by print command - - self.f_univ_newline = False # handle any newline convention - self.f_newlinetypes = 0 # types of newlines seen - self.f_skipnextlf = False # skip next \n - - self.mode = 0 - self.pos = 0 - self.size = 0 - - self.filename = filename - self.mode_string = "" + self.stream = stream + self.decompressor = W_BZ2Decompressor(space) + self.readlength = 0 + self.buffer = "" + self.finished = False - self._init_bz2file(mode, buffering, compresslevel) - - def _init_bz2file(self, mode_, buffering, compresslevel): - self.size = -1 - - name = self.filename - mode_char = "" - mode_list = mode_ - - if compresslevel < 1 or compresslevel > 9: - raise OperationError(self.space.w_ValueError, - self.space.wrap("compresslevel must be between 1 and 9")) - - for mode in mode_list: - error = False - - if mode in ['r', 'w']: - if mode_char: - error = True - mode_char = mode - elif mode == 'b': - pass - elif mode == 'U': - self.f_univ_newline = True - else: - error = True - - if error: - raise OperationError(self.space.w_ValueError, - self.space.wrap("invalid mode char %s" % mode)) - - if mode_char == "": - mode_char = 'r' - mode = ['wb', 'rb'][mode_char == 'r'] - self.mode_string = mode - - # open the file and set the buffer - try: - f = pythonapi.PyFile_FromString(name, mode) - except IOError: - raise OperationError(self.space.w_IOError, - self.space.wrap("cannot open file %s" % name)) - pythonapi.PyFile_SetBufSize(f, buffering) - - # store the FILE object - self._file = pythonapi.PyFile_AsFile(f) - - bzerror = c_int() - if mode_char == 'r': - x = c_int() # little trick for null former c_void_p argument - self.fp = libbz2.BZ2_bzReadOpen(byref(bzerror), self._file, - 0, 0, byref(x), 0) - else: - self.fp = libbz2.BZ2_bzWriteOpen(byref(bzerror), self._file, - compresslevel, 0, 0) - - if bzerror.value != BZ_OK: - _catch_bz2_error(self.space, bzerror.value) - - self.mode = [MODE_WRITE, MODE_READ][mode_char == 'r'] - - def __del__(self): - bzerror = c_int() - - if self.mode in (MODE_READ, MODE_READ_EOF): - libbz2.BZ2_bzReadClose(byref(bzerror), self.fp) - elif self.mode == MODE_WRITE: - libbz2.BZ2_bzWriteClose(byref(bzerror), self.fp, 0, None, None) - - _drop_readahead(self) - - def _check_if_closed(self): - if self.mode == MODE_CLOSED: - raise OperationError(self.space.w_ValueError, - self.space.wrap("I/O operation on closed file")) - def close(self): - """close() -> None or (perhaps) an integer + self.stream.close() - Close the file. Sets data attribute .closed to true. A closed file - cannot be used for further I/O operations.""" - - # this feature is not supported due to fclose(): - # close() may be called more than once without error. - - bzerror = c_int(BZ_OK) - - if self.mode in (MODE_READ, MODE_READ_EOF): - libbz2.BZ2_bzReadClose(byref(bzerror), self.fp) - elif self.mode == MODE_WRITE: - libbz2.BZ2_bzWriteClose(byref(bzerror), self.fp, 0, None, None) - - self.mode = MODE_CLOSED - - # close the underline file - ret = libc.fclose(self._file) - if ret != 0: - raise OperationError(self.space.w_IOError, - self.space.wrap(_get_error_msg())) - - if bzerror.value != BZ_OK: - return _catch_bz2_error(self.space, bzerror.value) - - return self.space.wrap(ret) - close.unwrap_spec = ['self'] - def tell(self): - """tell() -> int + return self.readlength - Return the current file position, an integer (may be a long integer).""" - - self._check_if_closed() - - return self.space.wrap(self.pos) - tell.unwrap_spec = ['self'] - - def seek(self, offset, whence=0): - """"seek(offset [, whence]) -> None - - Move to new file position. Argument offset is a byte count. Optional - argument whence defaults to 0 (offset from start of file, offset - should be >= 0); other values are 1 (move relative to current position, - positive or negative), and 2 (move relative to end of file, usually - negative, although many platforms allow seeking beyond the end of a file). - - Note that seeking of bz2 files is emulated, and depending on the parameters - the operation may be extremely slow.""" - - _drop_readahead(self) - self._check_if_closed() - - bufsize = SMALLCHUNK - buf = create_string_buffer(bufsize) - bytesread = 0 - bzerror = c_int() - - if self.mode not in (MODE_READ, MODE_READ_EOF): - raise OperationError(self.space.w_IOError, - self.space.wrap("seek works only while reading")) - - if whence == 2: - if self.size == -1: - while True: - chunksize, buf = _univ_newline_read(bzerror, self.fp, buf, - bufsize, self) - self.pos += chunksize - bytesread += chunksize - - if bzerror.value == BZ_STREAM_END: - break - elif bzerror.value != BZ_OK: - _catch_bz2_error(self.space, bzerror.value) - - self.mode = MODE_READ_EOF - self.size = self.pos - bytesread = 0 - offset += self.size - elif whence == 1: - offset += self.pos - - # Before getting here, offset must be the absolute position the file - # pointer should be set to. - if offset >= self.pos: - # we can move forward - offset -= self.pos - else: - # we cannot move back, so rewind the stream - libbz2.BZ2_bzReadClose(byref(bzerror), self.fp) - if bzerror.value != BZ_OK: - _catch_bz2_error(self.space, bzerror.value) - - ret = libc.fseek(self._file, 0, SEEK_SET) - if ret != 0: - raise OperationError(self.space.w_IOError, - self.space.wrap(_get_error_msg())) - - self.pos = 0 - self.fp = libbz2.BZ2_bzReadOpen(byref(bzerror), self._file, - 0, 0, None, 0) - if bzerror.value != BZ_OK: - _catch_bz2_error(self.space, bzerror.value) - - self.mode = MODE_READ - - if offset <= 0 or self.mode == MODE_READ_EOF: - return - - # Before getting here, offset must be set to the number of bytes - # to walk forward. - while True: - if (offset - bytesread) > bufsize: - readsize = bufsize + def seek(self, offset, whence): + if whence == 1: + if offset >= 0: + read = 0 + while read < offset: + read += len(self.read(offset - read)) else: - # offset might be wider that readsize, but the result - # of the subtraction is bound by buffersize (see the - # condition above). bufsize is 8192. - readsize = offset - bytesread - - chunksize, buf = _univ_newline_read(bzerror, self.fp, buf, - readsize, self) - self.pos += chunksize - bytesread += chunksize - - if bzerror.value == BZ_STREAM_END: - self.size = self.pos - self.mode = MODE_READ_EOF - break - elif bzerror.value != BZ_OK: - _catch_bz2_error(self.space, bzerror.value) - - if bytesread == offset: - break - seek.unwrap_spec = ['self', int, int] - - def readline(self, size=-1): - """readline([size]) -> string + pos = self.readlength + offset + self.seek(pos, 0) + elif whence == 0: + self.stream.seek(0, 0) + self.decompressor = W_BZ2Decompressor(self.space) + self.readlength = 0 + self.buffer = "" + self.finished = False + read = 0 + while read < offset: + length = len(self.read(offset - read)) + read += length + if not length: + break + else: + raise NotImplementedError - Return the next line from the file, as a string, retaining newline. - A non-negative size argument will limit the maximum number of bytes to - return (an incomplete line may be returned then). Return an empty - string at EOF.""" - - self._check_if_closed() - - if self.mode == MODE_READ_EOF: - return self.space.wrap("") - elif not self.mode == MODE_READ: - raise OperationError(self.space.w_IOError, - self.space.wrap("file is not ready for reading")) - - if size == 0: - return self.space.wrap("") + def readall(self): + w_result = self.decompressor.decompress(self.stream.readall()) + result = self.space.str_w(w_result) + self.readlength += len(result) + return result + + def read(self, n): + # XXX not nice + while not self.buffer: + if self.finished: + return "" + try: + w_read = self.decompressor.decompress(self.stream.read(n)) + except OperationError, e: + if e.match(self.space, self.space.w_EOFError): + self.finished = True + return "" + self.buffer = self.space.str_w(w_read) + if len(self.buffer) >= n: + result = self.buffer[:n] + self.buffer = self.buffer[n:] else: - size = [size, 0][size < 0] - return self.space.wrap(_getline(self.space, self, size)) - readline.unwrap_spec = ['self', int] - - def read(self, size=-1): - """read([size]) -> string + result = self.buffer + self.buffer = "" + self.readlength += len(result) + return result + + def try_to_find_file_descriptor(self): + return self.stream.try_to_find_file_descriptor() + + def write(self, s): + raise OperationError(self.space.w_IOError, + self.space.wrap("file is not ready for writing")) + + +class WriteBZ2Filter(Stream): + """Standard I/O stream filter that compresses the stream with bz2.""" + + def __init__(self, space, stream, compresslevel): + """NOT_RPYTHON""" + import bz2 + self.stream = stream + self.space = space + self.compressor = W_BZ2Compressor(space, compresslevel) + self.writtenlength = 0 + + def close(self): + self.stream.write(self.space.str_w(self.compressor.flush())) + self.stream.close() - Read at most size uncompressed bytes, returned as a string. If the size - argument is negative or omitted, read until EOF is reached.""" - - self._check_if_closed() - - if self.mode == MODE_READ_EOF: - return self.space.wrap("") - elif not self.mode == MODE_READ: - raise OperationError(self.space.w_IOError, - self.space.wrap("file is not ready for reading")) - - bufsize = [size, _new_buffer_size(0)][size < 0] - - if bufsize > MAXINT: - raise OperationError(self.space.w_OverflowError, - self.space.wrap( - "requested number of bytes is more than a Python string can hold")) - - bytesread = 0 - buf = create_string_buffer(bufsize) - bzerror = c_int() - while True: - chunksize, buf = _univ_newline_read(bzerror, self.fp, buf, - bufsize - bytesread, self) - self.pos += chunksize - bytesread += chunksize - - if bzerror.value == BZ_STREAM_END: - self.size = self.pos - self.mode = MODE_READ_EOF - break - elif bzerror.value != BZ_OK: - _catch_bz2_error(self.space, bzerror.value) - - if size < 0: - bufsize = _new_buffer_size(bufsize) - else: - break - - buf_lst = [c for c in buf.value] - if bytesread != bufsize: - assert bytesread >= 0 - return self.space.wrap("".join(buf_lst[0:bytesread])) - return self.space.wrap("".join(buf_lst)) - read.unwrap_spec = ['self', int] - - def readlines(self, size=0): - """"readlines([size]) -> list - - Call readline() repeatedly and return a list of lines read. - The optional size argument, if given, is an approximate bound on the - total number of bytes in the lines returned.""" - - self._check_if_closed() - - # it seems size definitely ignored in CPython, so... - lines = [] - while True: - w_line = self.readline() - line = self.space.str_w(w_line) - if not line: - break - lines.append(line) - - return self.space.newlist([self.space.wrap(i) for i in lines]) - readlines.unwrap_spec = ['self', int] - def write(self, data): - """write(data) -> None + self.stream.write(self.space.str_w(self.compressor.compress(data))) + self.writtenlength += len(data) - Write the 'data' string to file. Note that due to buffering, close() may - be needed before the file on disk reflects the data written.""" - - self._check_if_closed() - - if not self.mode == MODE_WRITE: - raise OperationError(self.space.w_IOError, - self.space.wrap("file is not ready for writing")) - - self.f_softspace = False - - bzerror = c_int() - bufsize = len(data) - buf = c_char_p(data) - libbz2.BZ2_bzWrite(byref(bzerror), self.fp, buf, bufsize) - self.pos += bufsize - - if bzerror.value != BZ_OK: - _catch_bz2_error(self.space, bzerror.value) - write.unwrap_spec = ['self', str] - - def writelines(self, w_sequence_of_strings): - self._check_if_closed() - - seq_w = self.space.unpackiterable(w_sequence_of_strings) - - for w_line in seq_w: - line = self.space.str_w(w_line) - self.write(line) - writelines.unwrap_spec = ['self', W_Root] - - # accessors for properties - def fget_newlines(space, self): - if self.f_newlinetypes == NEWLINE_UNKNOWN: - return space.w_None - elif self.f_newlinetypes == NEWLINE_CR: - return space.wrap('\r') - elif self.f_newlinetypes == NEWLINE_LF: - return space.wrap('\n') - elif self.f_newlinetypes == NEWLINE_CR|NEWLINE_LF: - return space.newtuple([space.wrap('\r'), space.wrap('\n')]) - elif self.f_newlinetypes == NEWLINE_CRLF: - return space.wrap("\r\n") - elif self.f_newlinetypes == NEWLINE_CR|NEWLINE_CRLF: - return space.newtuple([space.wrap('\r'), space.wrap("\r\n")]) - elif self.f_newlinetypes == NEWLINE_LF|NEWLINE_CRLF: - return space.newtuple([space.wrap('\n'), space.wrap("\r\n")]) - elif self.f_newlinetypes == NEWLINE_CR|NEWLINE_LF|NEWLINE_CRLF: - return space.newtuple([space.wrap('\r'), space.wrap('\n'), - space.wrap("\r\n")]) - else: - raise OperationError(space.w_SystemError, - space.wrap( - "Unknown newlines value 0x%x" % self.f_newlinetypes)) - - def fget_closed(space, self): - return space.wrap(self.mode == MODE_CLOSED) - - def next(self): - space = self.space - w_line = self.readline() - if space.int_w(space.len(w_line)) == 0: # EOF - raise OperationError(space.w_StopIteration, space.w_None) - return w_line - next.unwrap_spec = ['self'] - - def __iter__(self): - return self.space.wrap(self) - __iter__.unwrap_spec = ['self'] - - def xreadlines(self): - """xreadlines() -> self - - For backward compatibility. BZ2File objects now include the performance - optimizations previously implemented in the xreadlines module.""" - - return self.__iter__() - xreadlines.unwrap_spec = ['self'] - - -get_newlines = GetSetProperty(_BZ2File.fget_newlines, cls=_BZ2File) -get_closed = GetSetProperty(_BZ2File.fget_closed, cls=_BZ2File) -_BZ2File.typedef = TypeDef("_BZ2File", - close = interp2app(_BZ2File.close, unwrap_spec=_BZ2File.close.unwrap_spec), - tell = interp2app(_BZ2File.tell, unwrap_spec=_BZ2File.tell.unwrap_spec), - seek = interp2app(_BZ2File.seek, unwrap_spec=_BZ2File.seek.unwrap_spec), - readline = interp2app(_BZ2File.readline, - unwrap_spec=_BZ2File.readline.unwrap_spec), - readlines = interp2app(_BZ2File.readlines, - unwrap_spec=_BZ2File.readlines.unwrap_spec), - read = interp2app(_BZ2File.read, unwrap_spec=_BZ2File.read.unwrap_spec), - __iter__ = interp2app(_BZ2File.__iter__), - next = interp2app(_BZ2File.next), - xreadlines = interp2app(_BZ2File.xreadlines, - unwrap_spec=_BZ2File.xreadlines.unwrap_spec), - write = interp2app(_BZ2File.write, unwrap_spec=_BZ2File.write.unwrap_spec), - writelines = interp2app(_BZ2File.writelines, - unwrap_spec=_BZ2File.writelines.unwrap_spec), - newlines = get_newlines, - closed = get_closed, - name = interp_attrproperty("filename", _BZ2File), - mode = interp_attrproperty("mode_string", _BZ2File), - softspace = interp_attrproperty("f_softspace", _BZ2File), -) + def tell(self): + return self.writtenlength + + def seek(self, offset, whence): + raise OperationError(self.space.w_IOError, + self.space.wrap("seek works only while reading")) + + def read(self, n): + raise OperationError(self.space.w_IOError, + self.space.wrap("file is not ready for reading")) -class _BZ2Comp(Wrappable): + def readall(self): + raise OperationError(self.space.w_IOError, + self.space.wrap("file is not ready for reading")) + + def try_to_find_file_descriptor(self): + return self.stream.try_to_find_file_descriptor() + + +def descr_compressor__new__(space, w_subtype, compresslevel=9): + x = space.allocate_instance(W_BZ2Compressor, w_subtype) + x = space.interp_w(W_BZ2Compressor, x) + W_BZ2Compressor.__init__(x, space, compresslevel) + return space.wrap(x) +descr_compressor__new__.unwrap_spec = [ObjSpace, W_Root, int] + +class W_BZ2Compressor(Wrappable): + """BZ2Compressor([compresslevel=9]) -> compressor object + + Create a new compressor object. This object may be used to compress + data sequentially. If you want to compress data in one shot, use the + compress() function instead. The compresslevel parameter, if given, + must be a number between 1 and 9.""" def __init__(self, space, compresslevel): self.space = space self.bzs = bz_stream() self.running = False - self._init_bz2comp(compresslevel) + __init__.unwrap_spec = ['self', ObjSpace, int] def _init_bz2comp(self, compresslevel): if compresslevel < 1 or compresslevel > 9: @@ -909,15 +430,28 @@ return self.space.wrap(res) flush.unwrap_spec = ['self'] - -_BZ2Comp.typedef = TypeDef("_BZ2Comp", - compress = interp2app(_BZ2Comp.compress, - unwrap_spec=_BZ2Comp.compress.unwrap_spec), - flush = interp2app(_BZ2Comp.flush, unwrap_spec=_BZ2Comp.flush.unwrap_spec), +W_BZ2Compressor.typedef = TypeDef("BZ2Compressor", + __doc__ = W_BZ2Compressor.__doc__, + __new__ = interp2app(descr_compressor__new__), + compress = interp2app(W_BZ2Compressor.compress), + flush = interp2app(W_BZ2Compressor.flush), ) -class _BZ2Decomp(Wrappable): +def descr_decompressor__new__(space, w_subtype): + x = space.allocate_instance(W_BZ2Decompressor, w_subtype) + x = space.interp_w(W_BZ2Decompressor, x) + W_BZ2Decompressor.__init__(x, space) + return space.wrap(x) +descr_decompressor__new__.unwrap_spec = [ObjSpace, W_Root] + +class W_BZ2Decompressor(Wrappable): + """BZ2Decompressor() -> decompressor object + + Create a new decompressor object. This object may be used to decompress + data sequentially. If you want to decompress data in one shot, use the + decompress() function instead.""" + def __init__(self, space): self.space = space @@ -998,10 +532,11 @@ decompress.unwrap_spec = ['self', str] -_BZ2Decomp.typedef = TypeDef("_BZ2Decomp", - unused_data = interp_attrproperty("unused_data", _BZ2Decomp), - decompress = interp2app(_BZ2Decomp.decompress, - unwrap_spec=_BZ2Decomp.decompress.unwrap_spec), +W_BZ2Decompressor.typedef = TypeDef("BZ2Decompressor", + __doc__ = W_BZ2Decompressor.__doc__, + __new__ = interp2app(descr_decompressor__new__), + unused_data = interp_attrproperty("unused_data", W_BZ2Decompressor), + decompress = interp2app(W_BZ2Decompressor.decompress), ) @@ -1023,7 +558,7 @@ # data in one shot. We will check it later anyway. out_bufsize = in_bufsize + (in_bufsize / 100 + 1) + 600 - out_buf = create_string_buffer(out_bufsize) + out_buf = create_string_buffer(out_bufsize) in_buf = create_string_buffer(in_bufsize) in_buf.value = data @@ -1128,46 +663,5 @@ res = "".join([out_buf[i] for i in range(total_out) if out_buf[i] != '\x00']) libbz2.BZ2_bzDecompressEnd(byref(bzs)) - return space.wrap(res) + return space.wrap(res) decompress.unwrap_spec = [ObjSpace, str] - -def BZ2Compressor(space, compresslevel=9): - """BZ2Compressor([compresslevel=9]) -> compressor object - - Create a new compressor object. This object may be used to compress - data sequentially. If you want to compress data in one shot, use the - compress() function instead. The compresslevel parameter, if given, - must be a number between 1 and 9.""" - - return space.wrap(_BZ2Comp(space, compresslevel)) -BZ2Compressor.unwrap_spec = [ObjSpace, int] - -def BZ2Decompressor(space): - """BZ2Decompressor() -> decompressor object - - Create a new decompressor object. This object may be used to decompress - data sequentially. If you want to decompress data in one shot, use the - decompress() function instead.""" - - return space.wrap(_BZ2Decomp(space)) -BZ2Decompressor.unwrap_spec = [ObjSpace] - -def BZ2File(space, filename, mode='r', buffering=-1, compresslevel=9): - """BZ2File(name [, mode='r', buffering=0, compresslevel=9]) -> file object - - Open a bz2 file. The mode can be 'r' or 'w', for reading (default) or - writing. When opened for writing, the file will be created if it doesn't - exist, and truncated otherwise. If the buffering argument is given, 0 means - unbuffered, and larger numbers specify the buffer size. If compresslevel - is given, must be a number between 1 and 9. - - Add a 'U' to mode to open the file for input with universal newline - support. Any line ending in the input file will be seen as a '\\n' in - Python. Also, a file so opened gains the attribute 'newlines'; the value - for this attribute is one of None (no newline read yet), '\\r', '\\n', - '\\r\\n' or a tuple containing all the newline types seen. Universal - newlines are available only when reading.""" - - return space.wrap(_BZ2File(space, filename, mode, buffering, compresslevel)) -BZ2File.unwrap_spec = [ObjSpace, str, str, int, int] - Modified: pypy/dist/pypy/module/bz2/test/test_bz2_file.py ============================================================================== --- pypy/dist/pypy/module/bz2/test/test_bz2_file.py (original) +++ pypy/dist/pypy/module/bz2/test/test_bz2_file.py Tue Dec 26 18:24:57 2006 @@ -1,3 +1,4 @@ +import py from pypy.conftest import gettestobjspace import os @@ -10,11 +11,10 @@ DATA_CRLF = 'BZh91AY&SY\xaez\xbbN\x00\x01H\xdf\x80\x00\x12@\x02\xff\xf0\x01\x07n\x00?\xe7\xff\xe0@\x01\xbc\xc6`\x86*\x8d=M\xa9\x9a\x86\xd0L@\x0fI\xa6!\xa1\x13\xc8\x88jdi\x8d@\x03@\x1a\x1a\x0c\x0c\x83 \x00\xc4h2\x19\x01\x82D\x84e\t\xe8\x99\x89\x19\x1ah\x00\r\x1a\x11\xaf\x9b\x0fG\xf5(\x1b\x1f?\t\x12\xcf\xb5\xfc\x95E\x00ps\x89\x12^\xa4\xdd\xa2&\x05(\x87\x04\x98\x89u\xe40%\xb6\x19\'\x8c\xc4\x89\xca\x07\x0e\x1b!\x91UIFU%C\x994!DI\xd2\xfa\xf0\xf1N8W\xde\x13A\xf5\x9cr%?\x9f3;I45A\xd1\x8bT\xb1\xa4\xc7\x8d\x1a\\"\xad\xa1\xabyBg\x15\xb9l\x88\x88\x91k"\x94\xa4\xd4\x89\xae*\xa6\x0b\x10\x0c\xd6\xd4m\xe86\xec\xb5j\x8a\x86j\';\xca.\x01I\xf2\xaaJ\xe8\x88\x8cU+t3\xfb\x0c\n\xa33\x13r2\r\x16\xe0\xb3(\xbf\x1d\x83r\xe7M\xf0D\x1365\xd8\x88\xd3\xa4\x92\xcb2\x06\x04\\\xc1\xb0\xea//\xbek&\xd8\xe6+t\xe5\xa1\x13\xada\x16\xder5"w]\xa2i\xb7[\x97R \xe2IT\xcd;Z\x04dk4\xad\x8a\t\xd3\x81z\x10\xf1:^`\xab\x1f\xc5\xdc\x91N\x14$+\x9e\xae\xd3\x80' def create_temp_file(crlf=False): - f = open("foo", "wb") + f = py.test.ensuretemp("bz2").join("foo") data = (DATA, DATA_CRLF)[crlf] f.write(data) - f.close() def decompress(data): import popen2 @@ -34,10 +34,6 @@ mod.create_temp_file = create_temp_file mod.decompress = decompress -def teardown_module(mod): - if os.path.exists("foo"): - os.unlink("foo") - class AppTestBZ2File: def setup_class(cls): space = gettestobjspace(usemodules=('bz2',)) @@ -45,14 +41,15 @@ cls.w_TEXT = space.wrap(TEXT) cls.w_DATA = space.wrap(DATA) cls.w_DATA_CRLF = space.wrap(DATA_CRLF) + cls.w_temppath = space.wrap(str(py.test.ensuretemp("bz2").join("foo"))) cls.w_create_temp_file = space.wrap(create_temp_file) cls.w_decompress = space.wrap(decompress) def test_attributes(self): from bz2 import BZ2File - bz2f = BZ2File("foo", mode="w") - assert bz2f.name == "foo" + bz2f = BZ2File(self.temppath, mode="w") + assert bz2f.name == self.temppath assert bz2f.newlines == None assert bz2f.mode == "wb" assert bz2f.softspace == False @@ -63,36 +60,37 @@ def test_creation(self): from bz2 import BZ2File - raises(ValueError, BZ2File, "foo", mode='w', compresslevel=10) - raises(ValueError, BZ2File, "foo", mode='XYZ') - raises(ValueError, BZ2File, "foo", mode='ww') + raises(ValueError, BZ2File, self.temppath, mode='w', compresslevel=10) + raises(IOError, BZ2File, self.temppath, mode='XYZ') + # XXX the following is fine, currently: + #raises(ValueError, BZ2File, self.temppath, mode='ww') - BZ2File("foo", mode='wU', buffering=0, compresslevel=8) - BZ2File("foo", mode='wb') + BZ2File(self.temppath, mode='wU', buffering=0, compresslevel=8) + BZ2File(self.temppath, mode='wb') # a large buf size - BZ2File("foo", mode='w', buffering=4096) + BZ2File(self.temppath, mode='w', buffering=4096) def test_close(self): from bz2 import BZ2File # writeonly - bz2f = BZ2File("foo", mode='w') + bz2f = BZ2File(self.temppath, mode='w') bz2f.close() # since we use fclose() internally you can't close it twice # bz2f.close() # readonly - bz2f = BZ2File("foo", mode='r') + bz2f = BZ2File(self.temppath, mode='r') bz2f.close() def test_tell(self): from bz2 import BZ2File - bz2f = BZ2File("foo", mode='w') + bz2f = BZ2File(self.temppath, mode='w') bz2f.close() raises(ValueError, bz2f.tell) - bz2f = BZ2File("foo", mode='w') + bz2f = BZ2File(self.temppath, mode='w') pos = bz2f.tell() assert pos == 0 @@ -100,19 +98,19 @@ from bz2 import BZ2File # hack to create a foo file - open("foo", "w").close() + open(self.temppath, "w").close() # cannot seek if close - bz2f = BZ2File("foo", mode='r') + bz2f = BZ2File(self.temppath, mode='r') bz2f.close() raises(ValueError, bz2f.seek, 0) # cannot seek if 'w' - bz2f = BZ2File("foo", mode='w') + bz2f = BZ2File(self.temppath, mode='w') raises(IOError, bz2f.seek, 0) bz2f.close() - bz2f = BZ2File("foo", mode='r') + bz2f = BZ2File(self.temppath, mode='r') raises(TypeError, bz2f.seek) raises(TypeError, bz2f.seek, "foo") raises(TypeError, bz2f.seek, 0, "foo") @@ -124,8 +122,8 @@ from bz2 import BZ2File self.create_temp_file() - for i in range(10000): - f = BZ2File("foo") + for i in range(10): + f = BZ2File(self.temppath) f.close() del f @@ -138,9 +136,9 @@ from bz2 import BZ2File self.create_temp_file() - bz2f = BZ2File("foo", "U") + bz2f = BZ2File(self.temppath, "U") bz2f.close() - f = open("foo") + f = open(self.temppath) f.seek(0, 2) f.read() assert f.tell() == len(self.DATA) @@ -150,26 +148,28 @@ from bz2 import BZ2File self.create_temp_file() - bz2f = BZ2File("foo") + bz2f = BZ2File(self.temppath) bz2f.seek(150) # (150, 0) assert bz2f.read() == self.TEXT[150:] bz2f.close() def test_seek_backwards(self): + #skip("currently does not work") from bz2 import BZ2File self.create_temp_file() - bz2f = BZ2File("foo") + bz2f = BZ2File(self.temppath) bz2f.read(500) bz2f.seek(-150, 1) assert bz2f.read() == self.TEXT[500 - 150:] bz2f.close() def test_seek_backwards_from_end(self): + #skip("currently does not work") from bz2 import BZ2File self.create_temp_file() - bz2f = BZ2File("foo") + bz2f = BZ2File(self.temppath) bz2f.seek(-150, 2) assert bz2f.read() == self.TEXT[len(self.TEXT) - 150:] bz2f.close() @@ -178,7 +178,7 @@ from bz2 import BZ2File self.create_temp_file() - bz2f = BZ2File("foo") + bz2f = BZ2File(self.temppath) bz2f.seek(150000) assert bz2f.tell() == len(self.TEXT) assert bz2f.read() == "" @@ -188,7 +188,7 @@ from bz2 import BZ2File self.create_temp_file() - bz2f = BZ2File("foo") + bz2f = BZ2File(self.temppath) bz2f.seek(150000) bz2f.seek(150000) assert bz2f.tell() == len(self.TEXT) @@ -199,7 +199,7 @@ from bz2 import BZ2File self.create_temp_file() - bz2f = BZ2File("foo") + bz2f = BZ2File(self.temppath) bz2f.seek(-150) assert bz2f.tell() == 0 assert bz2f.read() == self.TEXT @@ -210,8 +210,9 @@ from cStringIO import StringIO self.create_temp_file() - bz2f = BZ2File("foo") - raises(TypeError, bz2f.readline, None) + bz2f = BZ2File(self.temppath) + # XXX + #raises(TypeError, bz2f.readline, None) sio = StringIO(self.TEXT) for line in sio.readlines(): line_read = bz2f.readline() @@ -222,31 +223,32 @@ from bz2 import BZ2File self.create_temp_file() - bz2f = BZ2File("foo") - raises(TypeError, bz2f.read, None) + bz2f = BZ2File(self.temppath) + # XXX + # raises(TypeError, bz2f.read, None) text_read = bz2f.read() - assert text_read == self.TEXT + assert text_read == self.TEXT bz2f.close() def test_read_chunk10(self): from bz2 import BZ2File self.create_temp_file() - bz2f = BZ2File("foo") + bz2f = BZ2File(self.temppath) text_read = "" while True: data = bz2f.read(10) if not data: break text_read = "%s%s" % (text_read, data) - assert text_read == self.TEXT + assert text_read == self.TEXT bz2f.close() def test_read_100_bytes(self): from bz2 import BZ2File self.create_temp_file() - bz2f = BZ2File("foo") + bz2f = BZ2File(self.temppath) assert bz2f.read(100) == self.TEXT[:100] bz2f.close() @@ -254,7 +256,7 @@ from bz2 import BZ2File self.create_temp_file() - bz2f = BZ2File("foo", "rU") + bz2f = BZ2File(self.temppath, "rU") assert bz2f.read() == self.TEXT assert bz2f.newlines == "\n" bz2f.close() @@ -263,7 +265,7 @@ from bz2 import BZ2File self.create_temp_file(crlf=True) - bz2f = BZ2File("foo", "rU") + bz2f = BZ2File(self.temppath, "rU") data = bz2f.read() assert data == self.TEXT assert bz2f.newlines == "\r\n" @@ -274,8 +276,9 @@ from cStringIO import StringIO self.create_temp_file() - bz2f = BZ2File("foo") - raises(TypeError, bz2f.readlines, None) + bz2f = BZ2File(self.temppath) + # XXX + #raises(TypeError, bz2f.readlines, None) sio = StringIO(self.TEXT) assert bz2f.readlines() == sio.readlines() bz2f.close() @@ -285,7 +288,7 @@ from cStringIO import StringIO self.create_temp_file() - bz2f = BZ2File("foo") + bz2f = BZ2File(self.temppath) sio = StringIO(self.TEXT) assert list(iter(bz2f)) == sio.readlines() bz2f.close() @@ -295,7 +298,7 @@ from cStringIO import StringIO self.create_temp_file() - bz2f = BZ2File("foo") + bz2f = BZ2File(self.temppath) sio = StringIO(self.TEXT) assert list(bz2f.xreadlines()) == sio.readlines() bz2f.close() @@ -305,36 +308,36 @@ from bz2 import BZ2File DATA = 'BZh91AY&SY\xd9b\x89]\x00\x00\x00\x03\x80\x04\x00\x02\x00\x0c\x00 \x00!\x9ah3M\x13<]\xc9\x14\xe1BCe\x8a%t' - f = open("foo", "wb") + f = open(self.temppath, "wb") f.write(DATA) f.close() - bz2f = BZ2File("foo") + bz2f = BZ2File(self.temppath) lines = bz2f.readlines() bz2f.close() assert lines == ['Test'] - bz2f = BZ2File("foo") + bz2f = BZ2File(self.temppath) xlines = list(bz2f.xreadlines()) bz2f.close() assert xlines == ['Test'] - def test_write(self): + def test_write(self): from bz2 import BZ2File - bz2f = BZ2File("foo", 'w') + bz2f = BZ2File(self.temppath, 'w') raises(TypeError, bz2f.write) bz2f.write(self.TEXT) bz2f.close() - f = open("foo", "rb") + f = open(self.temppath, "rb") assert self.decompress(f.read()) == self.TEXT f.close() def test_write_chunks_10(self): from bz2 import BZ2File - bz2f = BZ2File("foo", 'w') + bz2f = BZ2File(self.temppath, 'w') n = 0 while True: data = self.TEXT[n * 10:(n + 1) * 10] @@ -345,7 +348,7 @@ n += 1 bz2f.close() - f = open("foo", "rb") + f = open(self.temppath, "rb") assert self.decompress(f.read()) == self.TEXT f.close() @@ -353,19 +356,19 @@ from bz2 import BZ2File from cStringIO import StringIO - bz2f = BZ2File("foo", 'w') + bz2f = BZ2File(self.temppath, 'w') raises(TypeError, bz2f.writelines) sio = StringIO(self.TEXT) bz2f.writelines(sio.readlines()) bz2f.close() - f = open("foo", "rb") + f = open(self.temppath, "rb") assert self.decompress(f.read()) == self.TEXT f.close() def test_write_methods_on_readonly_file(self): from bz2 import BZ2File - bz2f = BZ2File("foo", 'r') + bz2f = BZ2File(self.temppath, 'r') raises(IOError, bz2f.write, "abc") raises(IOError, bz2f.writelines, ["abc"]) bz2f.close() From antocuni at codespeak.net Wed Dec 27 10:57:25 2006 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Wed, 27 Dec 2006 10:57:25 +0100 (CET) Subject: [pypy-svn] r35989 - pypy/dist/pypy/translator Message-ID: <20061227095725.3692C1007A@code0.codespeak.net> Author: antocuni Date: Wed Dec 27 10:57:24 2006 New Revision: 35989 Modified: pypy/dist/pypy/translator/driver.py Log: Use inlining by default when building pypy.net; disable constfold by now, because it's broken with ootypesystem. Modified: pypy/dist/pypy/translator/driver.py ============================================================================== --- pypy/dist/pypy/translator/driver.py (original) +++ pypy/dist/pypy/translator/driver.py Wed Dec 27 10:57:24 2006 @@ -351,11 +351,12 @@ inline_threshold=0, mallocs=False, merge_if_blocks=False, - constfold=True, + constfold=False, heap2stack=False, clever_malloc_removal=False) if self.config.translation.backend == 'cli': opt['merge_if_blocks'] = True + opt['inline_threshold'] = 1 backend_optimizations(self.translator, **opt) # task_backendopt_ootype = taskdef(task_backendopt_ootype, From antocuni at codespeak.net Wed Dec 27 11:32:08 2006 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Wed, 27 Dec 2006 11:32:08 +0100 (CET) Subject: [pypy-svn] r35991 - pypy/dist/pypy/rpython Message-ID: <20061227103208.A58A91007A@code0.codespeak.net> Author: antocuni Date: Wed Dec 27 11:32:07 2006 New Revision: 35991 Modified: pypy/dist/pypy/rpython/llinterp.py Log: Implement ooparse_float also for llinterp. Modified: pypy/dist/pypy/rpython/llinterp.py ============================================================================== --- pypy/dist/pypy/rpython/llinterp.py (original) +++ pypy/dist/pypy/rpython/llinterp.py Wed Dec 27 11:32:07 2006 @@ -902,6 +902,12 @@ except ValueError: self.make_llexception() + def op_ooparse_float(self, s): + try: + return ootype.ooparse_float(s) + except ValueError: + self.make_llexception() + def op_oohash(self, s): return ootype.oohash(s) From pedronis at codespeak.net Wed Dec 27 12:03:11 2006 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Wed, 27 Dec 2006 12:03:11 +0100 (CET) Subject: [pypy-svn] r35992 - pypy/dist/pypy/translator/llvm/test Message-ID: <20061227110311.1EE6F10079@code0.codespeak.net> Author: pedronis Date: Wed Dec 27 12:03:09 2006 New Revision: 35992 Modified: pypy/dist/pypy/translator/llvm/test/test_rtagged.py Log: skip if there's no llvm Modified: pypy/dist/pypy/translator/llvm/test/test_rtagged.py ============================================================================== --- pypy/dist/pypy/translator/llvm/test/test_rtagged.py (original) +++ pypy/dist/pypy/translator/llvm/test/test_rtagged.py Wed Dec 27 12:03:09 2006 @@ -62,10 +62,12 @@ # ____________________________________________________________ # only with Boehm so far +from pypy.translator.llvm.test import runtest from pypy.translator.interactive import Translation from pypy import conftest def test_tagged_boehm(): + runtest.llvm_test() t = Translation(entry_point, standalone=True, gc='boehm') try: exename = t.compile_llvm() From pedronis at codespeak.net Wed Dec 27 14:58:22 2006 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Wed, 27 Dec 2006 14:58:22 +0100 (CET) Subject: [pypy-svn] r35996 - in pypy/dist/pypy: doc translator/llvm Message-ID: <20061227135822.F0AB310086@code0.codespeak.net> Author: pedronis Date: Wed Dec 27 14:58:19 2006 New Revision: 35996 Modified: pypy/dist/pypy/doc/jit.txt pypy/dist/pypy/translator/llvm/externs2ll.py pypy/dist/pypy/translator/llvm/gc.py Log: calls Modified: pypy/dist/pypy/doc/jit.txt ============================================================================== --- pypy/dist/pypy/doc/jit.txt (original) +++ pypy/dist/pypy/doc/jit.txt Wed Dec 27 14:58:19 2006 @@ -615,7 +615,55 @@ Calls and inlining --------------------- -...green call... red call and inlining effect... gray call, yellow call... +For calls timeshifting can either produce code to generate a residual +call operation or recursively invoke the timeshifted version of the +callee. The residual operations generated by the timeshifted callee +will grow the compile-time produced residual function, this +effectively amounts to compile-time inlining the original callee into +its caller. + +Again timeshifting determines how to transform call operations based on +the color of arguments and result: + +* If all arguments and the result are green and we can detect the called + function not to have side-effects, the call is a so-called *green call*, + and will be left untouched which means there will be a call executed + at compile-time. + +* Calls to function that have no return value (i.e. their return type + is the low-level type Void), are assumed to have side-effects, they + are *gray calls*. + +* Calls with a green result but with side-effects are so-called *yellow calls*. + +* Calls with a red result are *red calls* + +The treatment of *red*, *gray* and *yellow* calls is similar, +timeshifting will transform them into calls to the timeshifted version +of the callee, resulting into an inlining-effect at compile time. + +At compile-time the JIT state contains a chain of virtual frames +(similar to `virtual structures`_), its top frame is updated with all +the red boxes for the call-point red variables before such calls and +the callee will attach a fresh new frame. This chain guarantees that +values (represented by the boxes) are propagated correctly, +accordingly split points duplicate and merge points treat the full +chain properly. + +Each timeshifted function has its own dispatch logic for splits, it +returns to the caller when all the split scheduled states have been +dealt with. A list of all the states that reached the return of the +function (there can be more than one) is returned to the caller which +then schedules these states on its dispatch queue. This is crucial for +yellow calls to keep the various green return values disjunct. + +What we have described applies to direct calls where the callee is a +constant function. For indirect calls, where the callee is a variable +it is checked whether the callee is constant at compile-time in which +case a mapping between the pointers to the original functions and +their timeshifted versions is used to call the appropriate timeshifted +callee as for a direct call. If the exact callee is unknown a residual +call operation is generated. Virtual structures Modified: pypy/dist/pypy/translator/llvm/externs2ll.py ============================================================================== --- pypy/dist/pypy/translator/llvm/externs2ll.py (original) +++ pypy/dist/pypy/translator/llvm/externs2ll.py Wed Dec 27 14:58:19 2006 @@ -36,7 +36,7 @@ plain = filename[:-2] includes = get_incdirs() - cmd = "llvm-gcc %s -S %s.c -o %s.ll 2>&1" % (includes, + cmd = "llvm-gcc %s -emit-llvm -S %s.c -o %s.ll 2>&1" % (includes, plain, plain) os.system(cmd) @@ -64,7 +64,7 @@ line = line.rstrip() # find function names, declare them with the default calling convertion - if line[-1:] == '{': + if line[-3:] == ') {': returntype, s = line.split(' ', 1) funcname , s = s.split('(', 1) funcnames[funcname] = True Modified: pypy/dist/pypy/translator/llvm/gc.py ============================================================================== --- pypy/dist/pypy/translator/llvm/gc.py (original) +++ pypy/dist/pypy/translator/llvm/gc.py Wed Dec 27 14:58:19 2006 @@ -6,6 +6,7 @@ log = log.gc def have_boehm(): + return True import distutils.sysconfig from os.path import exists libdir = distutils.sysconfig.EXEC_PREFIX + "/lib" From pedronis at codespeak.net Wed Dec 27 15:01:22 2006 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Wed, 27 Dec 2006 15:01:22 +0100 (CET) Subject: [pypy-svn] r35997 - pypy/dist/pypy/translator/llvm Message-ID: <20061227140122.A2C7D10086@code0.codespeak.net> Author: pedronis Date: Wed Dec 27 15:01:21 2006 New Revision: 35997 Modified: pypy/dist/pypy/translator/llvm/externs2ll.py pypy/dist/pypy/translator/llvm/gc.py Log: oops, this should not have been checked in Modified: pypy/dist/pypy/translator/llvm/externs2ll.py ============================================================================== --- pypy/dist/pypy/translator/llvm/externs2ll.py (original) +++ pypy/dist/pypy/translator/llvm/externs2ll.py Wed Dec 27 15:01:21 2006 @@ -36,7 +36,7 @@ plain = filename[:-2] includes = get_incdirs() - cmd = "llvm-gcc %s -emit-llvm -S %s.c -o %s.ll 2>&1" % (includes, + cmd = "llvm-gcc %s -S %s.c -o %s.ll 2>&1" % (includes, plain, plain) os.system(cmd) @@ -64,7 +64,7 @@ line = line.rstrip() # find function names, declare them with the default calling convertion - if line[-3:] == ') {': + if line[-1:] == '{': returntype, s = line.split(' ', 1) funcname , s = s.split('(', 1) funcnames[funcname] = True Modified: pypy/dist/pypy/translator/llvm/gc.py ============================================================================== --- pypy/dist/pypy/translator/llvm/gc.py (original) +++ pypy/dist/pypy/translator/llvm/gc.py Wed Dec 27 15:01:21 2006 @@ -6,7 +6,6 @@ log = log.gc def have_boehm(): - return True import distutils.sysconfig from os.path import exists libdir = distutils.sysconfig.EXEC_PREFIX + "/lib" From pedronis at codespeak.net Wed Dec 27 15:43:47 2006 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Wed, 27 Dec 2006 15:43:47 +0100 (CET) Subject: [pypy-svn] r35998 - pypy/dist/pypy/rpython/lltypesystem Message-ID: <20061227144347.0AE7E10086@code0.codespeak.net> Author: pedronis Date: Wed Dec 27 15:43:45 2006 New Revision: 35998 Modified: pypy/dist/pypy/rpython/lltypesystem/lloperation.py Log: add to table Modified: pypy/dist/pypy/rpython/lltypesystem/lloperation.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/lloperation.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/lloperation.py Wed Dec 27 15:43:45 2006 @@ -426,6 +426,7 @@ 'ooidentityhash': LLOp(oo=True, sideeffects=False), 'oostring': LLOp(oo=True, sideeffects=False), 'ooparse_int': LLOp(oo=True, canraise=(ValueError,)), + 'ooparse_float': LLOp(oo=True, canraise=(ValueError,)), 'oohash': LLOp(oo=True, sideeffects=False), } # ***** Run test_lloperation after changes. ***** From arigo at codespeak.net Wed Dec 27 16:55:55 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 27 Dec 2006 16:55:55 +0100 (CET) Subject: [pypy-svn] r36000 - pypy/extradoc/sprintinfo/leysin-winter-2007 Message-ID: <20061227155555.8493410083@code0.codespeak.net> Author: arigo Date: Wed Dec 27 16:55:52 2006 New Revision: 36000 Modified: pypy/extradoc/sprintinfo/leysin-winter-2007/people.txt Log: Add dates for the Merlinux people staying at the PyPy sprint (booking done according to dates sent by Lene) Modified: pypy/extradoc/sprintinfo/leysin-winter-2007/people.txt ============================================================================== --- pypy/extradoc/sprintinfo/leysin-winter-2007/people.txt (original) +++ pypy/extradoc/sprintinfo/leysin-winter-2007/people.txt Wed Dec 27 16:55:52 2006 @@ -23,6 +23,10 @@ Eric van Riet Paap 10th-14th Ermina Jacob Hallen 5th-15th Ermina Laura Creighton 5th-15th Ermina +Holger Krekel 5th-14th Ermina +Carl Friedrich Bolz 5th-14th Ermina +Guido Wesdorp 6th-14th Ermina +Leonardo Santagada 6th-14th Ermina ==================== ============== ===================== People on the following list were present at previous sprints: @@ -30,7 +34,6 @@ ==================== ============== ===================== Name Arrive/Depart Accomodation ==================== ============== ===================== -Holger Krekel ? ? Christian Tismer ? ? Michael Hudson ? ? Anders Lehmann ? ? @@ -44,11 +47,9 @@ Andrew Thompson ? ? Bert Freudenberg ? ? Beatrice Duering ? ? -Carl Friedrich Bolz ? ? Richard Emslie ? ? Johan Hahn ? ? Stephan Diehl ? ? Niko Matsakis ? ? -Leonardo Santagada ? ? Alexander Schremmer ? ? ==================== ============== ===================== From arigo at codespeak.net Wed Dec 27 19:40:00 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 27 Dec 2006 19:40:00 +0100 (CET) Subject: [pypy-svn] r36002 - in pypy/dist/pypy/rlib/rctypes: . test Message-ID: <20061227184000.89AD71008F@code0.codespeak.net> Author: arigo Date: Wed Dec 27 19:39:58 2006 New Revision: 36002 Added: pypy/dist/pypy/rlib/rctypes/rstruct.py (contents, props changed) pypy/dist/pypy/rlib/rctypes/test/__init__.py (contents, props changed) Modified: pypy/dist/pypy/rlib/rctypes/implementation.py pypy/dist/pypy/rlib/rctypes/rarray.py pypy/dist/pypy/rlib/rctypes/test/test_rprimitive.py Log: Start some ctypes.Structure support. Modified: pypy/dist/pypy/rlib/rctypes/implementation.py ============================================================================== --- pypy/dist/pypy/rlib/rctypes/implementation.py (original) +++ pypy/dist/pypy/rlib/rctypes/implementation.py Wed Dec 27 19:39:58 2006 @@ -149,3 +149,4 @@ import pypy.rlib.rctypes.rprimitive import pypy.rlib.rctypes.rarray import pypy.rlib.rctypes.rpointer +import pypy.rlib.rctypes.rstruct Modified: pypy/dist/pypy/rlib/rctypes/rarray.py ============================================================================== --- pypy/dist/pypy/rlib/rctypes/rarray.py (original) +++ pypy/dist/pypy/rlib/rctypes/rarray.py Wed Dec 27 19:39:58 2006 @@ -18,15 +18,15 @@ self.itemcontroller.knowntype, self.length) - def new(self, *args_s): - if len(args_s) > self.length: - raise ValueError("too many arguments for an array of length %d" % ( - self.length,)) + def new(self, *args): obj = self.knowntype.allocate() - if len(args_s) > 0: - lst_s = list(args_s) - for i in range(len(args_s)): - self.setitem(obj, i, lst_s[i]) + if args: + if len(args) > self.length: + raise ValueError("too many arguments for an array of " + "length %d" % (self.length,)) + lst = list(args) + for i in range(len(args)): + self.setitem(obj, i, lst[i]) return obj new._annspecialcase_ = 'specialize:arg(0)' Added: pypy/dist/pypy/rlib/rctypes/rstruct.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/rlib/rctypes/rstruct.py Wed Dec 27 19:39:58 2006 @@ -0,0 +1,54 @@ +from pypy.rlib.rctypes.implementation import CTypeController, getcontroller +from pypy.rlib.rctypes import rctypesobject +from pypy.rpython.lltypesystem import lltype +from pypy.rlib.unroll import unrolling_iterable + +from ctypes import Structure + +StructType = type(Structure) + + +class StructCTypeController(CTypeController): + + def __init__(self, ctype): + CTypeController.__init__(self, ctype) + + # Map the field names to their controllers + controllers = [] + fields = [] + for name, field_ctype in ctype._fields_: + controller = getcontroller(field_ctype) + controllers.append((name, controller)) + fields.append((name, controller.knowntype)) + self.fieldcontrollers = dict(controllers) + external = getattr(ctype, '_external_', False) + self.knowntype = rctypesobject.RStruct(ctype.__name__, fields, + c_external = external) + + # Build a custom new() method where the setting of the fields + # is unrolled + unrolled_controllers = unrolling_iterable(controllers) + + def new(*args): + obj = self.knowntype.allocate() + if len(args) > len(fields): + raise ValueError("too many arguments for this structure") + for name, controller in unrolled_controllers: + if args: + value = args[0] + args = args[1:] + itemobj = getattr(obj, 'ref_' + name)() + controller.set_value(itemobj, value) + return obj + + self.new = new + + + def getattr(self, obj, attr): + controller = self.fieldcontrollers[attr] + itemobj = getattr(obj, 'ref_' + attr)() + return controller.return_value(itemobj) + getattr._annspecialcase_ = 'specialize:arg(2)' + + +StructCTypeController.register_for_metatype(StructType) Added: pypy/dist/pypy/rlib/rctypes/test/__init__.py ============================================================================== Modified: pypy/dist/pypy/rlib/rctypes/test/test_rprimitive.py ============================================================================== --- pypy/dist/pypy/rlib/rctypes/test/test_rprimitive.py (original) +++ pypy/dist/pypy/rlib/rctypes/test/test_rprimitive.py Wed Dec 27 19:39:58 2006 @@ -158,7 +158,6 @@ t.view() def test_annotate_primitive_structfield(self): - py.test.skip("in-progress") class S(Structure): _fields_ = [('cs', c_short)] def func(x): From arigo at codespeak.net Wed Dec 27 19:44:33 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 27 Dec 2006 19:44:33 +0100 (CET) Subject: [pypy-svn] r36003 - in pypy/dist/pypy/rlib/rctypes: . test Message-ID: <20061227184433.46A8E10092@code0.codespeak.net> Author: arigo Date: Wed Dec 27 19:44:30 2006 New Revision: 36003 Modified: pypy/dist/pypy/rlib/rctypes/rpointer.py pypy/dist/pypy/rlib/rctypes/test/test_rprimitive.py Log: Assignment to pointer[0]. Modified: pypy/dist/pypy/rlib/rctypes/rpointer.py ============================================================================== --- pypy/dist/pypy/rlib/rctypes/rpointer.py (original) +++ pypy/dist/pypy/rlib/rctypes/rpointer.py Wed Dec 27 19:44:30 2006 @@ -30,6 +30,13 @@ return self.contentscontroller.return_value(contentsobj) getitem._annspecialcase_ = 'specialize:arg(0)' + def setitem(self, obj, index, value): + if index != 0: + raise ValueError("assignment to pointer[x] with x != 0") + # not supported by ctypes either + contentsobj = obj.get_contents() + self.contentscontroller.set_value(contentsobj, value) + PointerCTypeController.register_for_metatype(PointerType) register_function_impl(pointer, rctypesobject.pointer, Modified: pypy/dist/pypy/rlib/rctypes/test/test_rprimitive.py ============================================================================== --- pypy/dist/pypy/rlib/rctypes/test/test_rprimitive.py (original) +++ pypy/dist/pypy/rlib/rctypes/test/test_rprimitive.py Wed Dec 27 19:44:30 2006 @@ -202,7 +202,6 @@ t.view() def test_annotate_set_primitive_ptritem(self): - py.test.skip("in-progress") def func(x): cs = pointer(c_short()) cs[0] = x From arigo at codespeak.net Wed Dec 27 19:46:56 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 27 Dec 2006 19:46:56 +0100 (CET) Subject: [pypy-svn] r36004 - in pypy/dist/pypy/rlib/rctypes: . test Message-ID: <20061227184656.229DE1008F@code0.codespeak.net> Author: arigo Date: Wed Dec 27 19:46:54 2006 New Revision: 36004 Modified: pypy/dist/pypy/rlib/rctypes/rstruct.py pypy/dist/pypy/rlib/rctypes/test/test_rprimitive.py Log: Assignment to struct fields. Modified: pypy/dist/pypy/rlib/rctypes/rstruct.py ============================================================================== --- pypy/dist/pypy/rlib/rctypes/rstruct.py (original) +++ pypy/dist/pypy/rlib/rctypes/rstruct.py Wed Dec 27 19:46:54 2006 @@ -50,5 +50,11 @@ return controller.return_value(itemobj) getattr._annspecialcase_ = 'specialize:arg(2)' + def setattr(self, obj, attr, value): + controller = self.fieldcontrollers[attr] + itemobj = getattr(obj, 'ref_' + attr)() + controller.set_value(itemobj, value) + setattr._annspecialcase_ = 'specialize:arg(2)' + StructCTypeController.register_for_metatype(StructType) Modified: pypy/dist/pypy/rlib/rctypes/test/test_rprimitive.py ============================================================================== --- pypy/dist/pypy/rlib/rctypes/test/test_rprimitive.py (original) +++ pypy/dist/pypy/rlib/rctypes/test/test_rprimitive.py Wed Dec 27 19:46:54 2006 @@ -216,7 +216,6 @@ t.view() def test_annotate_set_primitive_structfield(self): - py.test.skip("in-progress") class S(Structure): _fields_ = [('cs', c_short)] def func(x): From arigo at codespeak.net Wed Dec 27 19:54:14 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 27 Dec 2006 19:54:14 +0100 (CET) Subject: [pypy-svn] r36005 - pypy/dist/pypy/rpython/test Message-ID: <20061227185414.535591008F@code0.codespeak.net> Author: arigo Date: Wed Dec 27 19:54:12 2006 New Revision: 36005 Modified: pypy/dist/pypy/rpython/test/test_controllerentry.py Log: A (skipped) failing test showing a messy issue in convert_const(). Modified: pypy/dist/pypy/rpython/test/test_controllerentry.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_controllerentry.py (original) +++ pypy/dist/pypy/rpython/test/test_controllerentry.py Wed Dec 27 19:54:12 2006 @@ -1,3 +1,4 @@ +import py from pypy.rpython.controllerentry import Controller, ControllerEntry from pypy.rpython.controllerentry import ControllerEntryForPrebuilt @@ -61,6 +62,19 @@ c3 = C() c3._bar = 7654 +def fun1(): + return c2.foo + +def test_C1_annotate(): + a = RPythonAnnotator() + s = a.build_types(fun1, []) + assert s.const == "512" + +def test_C1_specialize(): + py.test.skip("argh! what can we do about it?") + res = interpret(fun1, []) + assert ''.join(res.chars) == "512" + def fun2(flag): if flag: c = c2 From arigo at codespeak.net Wed Dec 27 20:08:33 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 27 Dec 2006 20:08:33 +0100 (CET) Subject: [pypy-svn] r36006 - in pypy/dist/pypy/rpython: . test Message-ID: <20061227190833.4812C10090@code0.codespeak.net> Author: arigo Date: Wed Dec 27 20:08:32 2006 New Revision: 36006 Modified: pypy/dist/pypy/rpython/rcontrollerentry.py pypy/dist/pypy/rpython/test/test_controllerentry.py Log: There is actually a "simple" workaround for this problem. Modified: pypy/dist/pypy/rpython/rcontrollerentry.py ============================================================================== --- pypy/dist/pypy/rpython/rcontrollerentry.py (original) +++ pypy/dist/pypy/rpython/rcontrollerentry.py Wed Dec 27 20:08:32 2006 @@ -26,6 +26,10 @@ for index in revealargs: s_new, r_new = self.reveal(hop2.args_r[index]) hop2.args_s[index], hop2.args_r[index] = s_new, r_new + v = hop2.args_v[index] + if isinstance(v, Constant): + real_value = self.controller.convert(v.value) + hop2.args_v[index] = Constant(real_value) if revealresult: hop2.s_result, hop2.r_result = self.reveal(hop2.r_result) hop2.v_s_insertfirstarg(c_meth, s_meth) Modified: pypy/dist/pypy/rpython/test/test_controllerentry.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_controllerentry.py (original) +++ pypy/dist/pypy/rpython/test/test_controllerentry.py Wed Dec 27 20:08:32 2006 @@ -71,7 +71,6 @@ assert s.const == "512" def test_C1_specialize(): - py.test.skip("argh! what can we do about it?") res = interpret(fun1, []) assert ''.join(res.chars) == "512" From arigo at codespeak.net Wed Dec 27 21:00:03 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 27 Dec 2006 21:00:03 +0100 (CET) Subject: [pypy-svn] r36007 - in pypy/dist/pypy/rpython: . test Message-ID: <20061227200003.A6D5710082@code0.codespeak.net> Author: arigo Date: Wed Dec 27 21:00:00 2006 New Revision: 36007 Modified: pypy/dist/pypy/rpython/rbuiltin.py pypy/dist/pypy/rpython/test/test_rbuiltin.py Log: If necessary, generate a 'cast_primitive' operation when rtyping lltype.cast_primitive(). Modified: pypy/dist/pypy/rpython/rbuiltin.py ============================================================================== --- pypy/dist/pypy/rpython/rbuiltin.py (original) +++ pypy/dist/pypy/rpython/rbuiltin.py Wed Dec 27 21:00:00 2006 @@ -434,13 +434,17 @@ return v_value if (isinstance(TGT, lltype.Primitive) and isinstance(ORIG, lltype.Primitive)): - op = _cast_to_Signed[ORIG] - if op: - v_value = llops.genop(op, [v_value], resulttype = lltype.Signed) - op = _cast_from_Signed[TGT] - if op: - v_value = llops.genop(op, [v_value], resulttype = TGT) - return v_value + if ORIG in _cast_to_Signed and TGT in _cast_from_Signed: + op = _cast_to_Signed[ORIG] + if op: + v_value = llops.genop(op, [v_value], resulttype=lltype.Signed) + op = _cast_from_Signed[TGT] + if op: + v_value = llops.genop(op, [v_value], resulttype=TGT) + return v_value + else: + # use the generic operation if there is no alternative + return llops.genop('cast_primitive', [v_value], resulttype=TGT) elif isinstance(TGT, lltype.Ptr): if isinstance(ORIG, lltype.Ptr): if (isinstance(TGT.TO, lltype.OpaqueType) or 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 Dec 27 21:00:00 2006 @@ -6,6 +6,7 @@ from pypy.rlib.rarithmetic import r_uint, intmask from pypy.annotation.builtin import * from pypy.rpython.test.tool import BaseRtypingTest, LLRtypeMixin, OORtypeMixin +from pypy.rpython.rctypes.rcarithmetic import CShort import py @@ -386,6 +387,10 @@ return lltype.cast_primitive(lltype.UniChar, v) res = self.interpret(llf, [ord('x')], policy=LowLevelAnnotatorPolicy()) assert res == u'x' + def llf(v): + return lltype.cast_primitive(CShort, v) + res = self.interpret(llf, [123], policy=LowLevelAnnotatorPolicy()) + assert res == 123 From pedronis at codespeak.net Wed Dec 27 22:23:21 2006 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Wed, 27 Dec 2006 22:23:21 +0100 (CET) Subject: [pypy-svn] r36008 - in pypy/dist/pypy: annotation objspace/flow/test rpython rpython/lltypesystem rpython/ootypesystem rpython/test translator Message-ID: <20061227212321.310CF10084@code0.codespeak.net> Author: pedronis Date: Wed Dec 27 22:23:16 2006 New Revision: 36008 Modified: pypy/dist/pypy/annotation/annrpython.py pypy/dist/pypy/annotation/binaryop.py pypy/dist/pypy/annotation/model.py pypy/dist/pypy/objspace/flow/test/test_objspace.py pypy/dist/pypy/rpython/lltypesystem/rstr.py pypy/dist/pypy/rpython/ootypesystem/ootype.py pypy/dist/pypy/rpython/rlist.py pypy/dist/pypy/rpython/rmodel.py pypy/dist/pypy/rpython/rstr.py pypy/dist/pypy/rpython/test/test_llinterp.py pypy/dist/pypy/rpython/test/test_rlist.py pypy/dist/pypy/rpython/test/test_rstr.py pypy/dist/pypy/translator/geninterplevel.py pypy/dist/pypy/translator/simplify.py Log: Better precision for when to generate bound checking versions of getitem. Have a transformation that rename getitem into getitem(_idx)(_key) based on whether the getitem is effectively guarded by such exception (IndexError, KeyError) exits. Change annotation and rtyping to work accordingly. Done with more precision for lists and strings for now, fallbacks in place for the rest. (Should be done for setitem too) Tests for the transformation in objspace/flow and for the final behavior in the rpython/test. Modified: pypy/dist/pypy/annotation/annrpython.py ============================================================================== --- pypy/dist/pypy/annotation/annrpython.py (original) +++ pypy/dist/pypy/annotation/annrpython.py Wed Dec 27 22:23:16 2006 @@ -591,11 +591,11 @@ arg1 = self.binding(op.args[0]) arg2 = self.binding(op.args[1]) binop = getattr(pair(arg1, arg2), op.opname, None) - can_only_throw = read_can_only_throw(binop, arg1, arg2) + can_only_throw = annmodel.read_can_only_throw(binop, arg1, arg2) elif op.opname in annmodel.UNARY_OPERATIONS: arg1 = self.binding(op.args[0]) unop = getattr(arg1, op.opname, None) - can_only_throw = read_can_only_throw(unop, arg1) + can_only_throw = annmodel.read_can_only_throw(unop, arg1) else: can_only_throw = None @@ -814,9 +814,3 @@ return "" %(break_at, self.op) __str__ = __repr__ - -def read_can_only_throw(opimpl, *args): - can_only_throw = getattr(opimpl, "can_only_throw", None) - if can_only_throw is None or isinstance(can_only_throw, list): - return can_only_throw - return can_only_throw(*args) Modified: pypy/dist/pypy/annotation/binaryop.py ============================================================================== --- pypy/dist/pypy/annotation/binaryop.py (original) +++ pypy/dist/pypy/annotation/binaryop.py Wed Dec 27 22:23:16 2006 @@ -16,6 +16,7 @@ from pypy.annotation.model import SomeWeakGcAddress from pypy.annotation.model import SomeCTypesObject from pypy.annotation.model import unionof, UnionError, set, missing_operation, 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 from pypy.annotation.bookkeeper import getbookkeeper @@ -34,6 +35,7 @@ 'and_', 'or_', 'xor', 'lshift', 'rshift', 'getitem', 'setitem', 'delitem', + 'getitem_idx', 'getitem_key', 'getitem_idx_key', 'inplace_add', 'inplace_sub', 'inplace_mul', 'inplace_truediv', 'inplace_floordiv', 'inplace_div', 'inplace_mod', 'inplace_pow', @@ -214,6 +216,20 @@ else: return obj + # checked getitems + + def _getitem_can_only_throw(s_c1, s_o2): + impl = pair(s_c1, s_o2).getitem + return read_can_only_throw(impl, s_c1, s_o2) + + def getitem_idx_key((s_c1, s_o2)): + impl = pair(s_c1, s_o2).getitem + return impl() + getitem_idx_key.can_only_throw = _getitem_can_only_throw + + getitem_idx = getitem_idx_key + getitem_key = getitem_idx_key + # cloning a function with identical code, for the can_only_throw attribute def _clone(f, can_only_throw = None): @@ -512,7 +528,16 @@ def getitem((lst1, int2)): getbookkeeper().count("list_getitem", int2) return lst1.listdef.read_item() - getitem.can_only_throw = [IndexError] + getitem.can_only_throw = [] + + getitem_key = getitem + + def getitem_idx((lst1, int2)): + getbookkeeper().count("list_getitem", int2) + return lst1.listdef.read_item() + getitem_idx.can_only_throw = [IndexError] + + getitem_idx_key = getitem_idx def setitem((lst1, int2), s_value): getbookkeeper().count("list_setitem", int2) @@ -552,7 +577,16 @@ def getitem((str1, int2)): getbookkeeper().count("str_getitem", int2) return SomeChar() - getitem.can_only_throw = [IndexError] + getitem.can_only_throw = [] + + getitem_key = getitem + + def getitem_idx((str1, int2)): + getbookkeeper().count("str_getitem", int2) + return SomeChar() + getitem_idx.can_only_throw = [IndexError] + + getitem_idx_key = getitem_idx def mul((str1, int2)): # xxx do we want to support this getbookkeeper().count("str_mul", str1, int2) Modified: pypy/dist/pypy/annotation/model.py ============================================================================== --- pypy/dist/pypy/annotation/model.py (original) +++ pypy/dist/pypy/annotation/model.py Wed Dec 27 22:23:16 2006 @@ -718,6 +718,13 @@ BlockedInference: the current block is blocked, but not in a way that gives 'Blocked block' errors at the end of annotation.""" + +def read_can_only_throw(opimpl, *args): + can_only_throw = getattr(opimpl, "can_only_throw", None) + if can_only_throw is None or isinstance(can_only_throw, list): + return can_only_throw + return can_only_throw(*args) + # # safety check that no-one is trying to make annotation and translation # faster by providing the -O option to Python. Modified: pypy/dist/pypy/objspace/flow/test/test_objspace.py ============================================================================== --- pypy/dist/pypy/objspace/flow/test/test_objspace.py (original) +++ pypy/dist/pypy/objspace/flow/test/test_objspace.py Wed Dec 27 22:23:16 2006 @@ -711,6 +711,90 @@ return x[s] graph = self.codetest(myfunc) + def test_getitem(self): + def f(c, x): + try: + return c[x] + except Exception: + raise + graph = self.codetest(f) + simplify_graph(graph) + assert self.all_operations(graph) == {'getitem_idx_key': 1} + + g = lambda: None + def f(c, x): + try: + return c[x] + finally: + g() + graph = self.codetest(f) + simplify_graph(graph) + assert self.all_operations(graph) == {'getitem_idx_key': 1, + 'simple_call': 2} + + def f(c, x): + try: + return c[x] + except IndexError: + raise + graph = self.codetest(f) + simplify_graph(graph) + assert self.all_operations(graph) == {'getitem_idx': 1} + + def f(c, x): + try: + return c[x] + except KeyError: + raise + graph = self.codetest(f) + simplify_graph(graph) + assert self.all_operations(graph) == {'getitem_key': 1} + + def f(c, x): + try: + return c[x] + except ValueError: + raise + graph = self.codetest(f) + simplify_graph(graph) + assert self.all_operations(graph) == {'getitem': 1} + + def f(c, x): + try: + return c[x] + except Exception: + return -1 + graph = self.codetest(f) + simplify_graph(graph) + self.show(graph) + assert self.all_operations(graph) == {'getitem_idx_key': 1} + + def f(c, x): + try: + return c[x] + except IndexError: + return -1 + graph = self.codetest(f) + simplify_graph(graph) + assert self.all_operations(graph) == {'getitem_idx': 1} + + def f(c, x): + try: + return c[x] + except KeyError: + return -1 + graph = self.codetest(f) + simplify_graph(graph) + assert self.all_operations(graph) == {'getitem_key': 1} + + def f(c, x): + try: + return c[x] + except ValueError: + return -1 + graph = self.codetest(f) + simplify_graph(graph) + assert self.all_operations(graph) == {'getitem': 1} class TestFlowObjSpaceDelay(Base): def setup_class(cls): Modified: pypy/dist/pypy/rpython/lltypesystem/rstr.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/rstr.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/rstr.py Wed Dec 27 22:23:16 2006 @@ -160,7 +160,10 @@ return len(s.chars) def ll_stritem_nonneg(s, i): - return s.chars[i] + chars = s.chars + debug_assert(i>=0, "negative str getitem index") + debug_assert(i= 0 - return self._str[i] + s = self._str + assert 0 <= i < len(s) + return s[i] def ll_strlen(self): # NOT_RPYTHON Modified: pypy/dist/pypy/rpython/rlist.py ============================================================================== --- pypy/dist/pypy/rpython/rlist.py (original) +++ pypy/dist/pypy/rpython/rlist.py Wed Dec 27 22:23:16 2006 @@ -213,8 +213,8 @@ class __extend__(pairtype(AbstractBaseListRepr, IntegerRepr)): - def rtype_getitem((r_lst, r_int), hop): - if hop.has_implicit_exception(IndexError): + def rtype_getitem((r_lst, r_int), hop, checkidx=False): + if checkidx: spec = dum_checkidx else: spec = dum_nocheck @@ -224,10 +224,20 @@ llfn = ll_getitem_nonneg else: llfn = ll_getitem - hop.exception_is_here() + if checkidx: + hop.exception_is_here() + else: + hop.exception_cannot_occur() v_res = hop.gendirectcall(llfn, v_func, v_lst, v_index) return r_lst.recast(hop.llops, v_res) + rtype_getitem_key = rtype_getitem + + def rtype_getitem_idx((r_lst, r_int), hop): + return pair(r_lst, r_int).rtype_getitem(hop, checkidx=True) + + rtype_getitem_idx_key = rtype_getitem_idx + def rtype_setitem((r_lst, r_int), hop): if hop.has_implicit_exception(IndexError): spec = dum_checkidx Modified: pypy/dist/pypy/rpython/rmodel.py ============================================================================== --- pypy/dist/pypy/rpython/rmodel.py (original) +++ pypy/dist/pypy/rpython/rmodel.py Wed Dec 27 22:23:16 2006 @@ -1,4 +1,4 @@ -from pypy.annotation.pairtype import pairtype, extendabletype +from pypy.annotation.pairtype import pairtype, extendabletype, pair from pypy.annotation import model as annmodel from pypy.annotation import description from pypy.objspace.flow.model import Constant @@ -296,6 +296,14 @@ return inputconst(Bool, hop.s_result.const) return hop.rtyper.type_system.generic_is(robj1, robj2, hop) + # default implementation for checked getitems + + def rtype_getitem_idx_key((r_c1, r_o1), hop): + return pair(r_c1, r_o1).rtype_getitem(hop) + + rtype_getitem_idx = rtype_getitem_idx_key + rtype_getitem_key = rtype_getitem_idx_key + # ____________________________________________________________ Modified: pypy/dist/pypy/rpython/rstr.py ============================================================================== --- pypy/dist/pypy/rpython/rstr.py (original) +++ pypy/dist/pypy/rpython/rstr.py Wed Dec 27 22:23:16 2006 @@ -1,5 +1,5 @@ from pypy.tool.staticmethods import StaticMethods -from pypy.annotation.pairtype import pairtype +from pypy.annotation.pairtype import pairtype, pair from pypy.annotation import model as annmodel from pypy.rpython.error import TyperError from pypy.rpython.rmodel import IntegerRepr, IteratorRepr @@ -243,10 +243,10 @@ class __extend__(pairtype(AbstractStringRepr, IntegerRepr)): - def rtype_getitem((r_str, r_int), hop): + def rtype_getitem((r_str, r_int), hop, checkidx=False): string_repr = hop.rtyper.type_system.rstr.string_repr v_str, v_index = hop.inputargs(string_repr, Signed) - if hop.has_implicit_exception(IndexError): + if checkidx: if hop.args_s[1].nonneg: llfn = r_str.ll.ll_stritem_nonneg_checked else: @@ -256,9 +256,19 @@ llfn = r_str.ll.ll_stritem_nonneg else: llfn = r_str.ll.ll_stritem - hop.exception_is_here() + if checkidx: + hop.exception_is_here() + else: + hop.exception_cannot_occur() return hop.gendirectcall(llfn, v_str, v_index) + rtype_getitem_key = rtype_getitem + + def rtype_getitem_idx((r_str, r_int), hop): + return pair(r_str, r_int).rtype_getitem(hop, checkidx=True) + + rtype_getitem_idx_key = rtype_getitem_idx + class __extend__(pairtype(AbstractStringRepr, AbstractSliceRepr)): Modified: pypy/dist/pypy/rpython/test/test_llinterp.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_llinterp.py (original) +++ pypy/dist/pypy/rpython/test/test_llinterp.py Wed Dec 27 22:23:16 2006 @@ -105,7 +105,11 @@ someobjects, type_system=type_system, backendopt=backendopt) info = py.test.raises(LLException, "interp.eval_graph(graph, values)") - assert interp.find_exception(info.value) is exc, "wrong exception type" + try: + got = interp.find_exception(info.value) + except ValueError: + got = None + assert got is exc, "wrong exception type" #__________________________________________________________________ # tests Modified: pypy/dist/pypy/rpython/test/test_rlist.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_rlist.py (original) +++ pypy/dist/pypy/rpython/test/test_rlist.py Wed Dec 27 22:23:16 2006 @@ -1037,6 +1037,109 @@ res = self.interpret(dummyfn, [1, 0]) assert res == 0 + + def test_getitem_exc(self): + def f(x): + l = [1] + return l[x] + + res = self.interpret(f, [0]) + assert res == 1 + py.test.raises(AssertionError, self.interpret, f, [1]) + + def f(x): + l = [1] + try: + return l[x] + except IndexError: + return -1 + except Exception: + return 0 + + res = self.interpret(f, [0]) + assert res == 1 + res = self.interpret(f, [1]) + assert res == -1 + + def f(x): + l = [1] + try: + return l[x] + except Exception: + return 0 + + res = self.interpret(f, [0]) + assert res == 1 + res = self.interpret(f, [1]) + assert res == 0 + + def f(x): + l = [1] + try: + return l[x] + except ValueError: + return 0 + + res = self.interpret(f, [0]) + assert res == 1 + + def test_getitem_exc(self): + def f(x): + l = [1] + return l[x] + + res = self.interpret(f, [0]) + assert res == 1 + try: + self.interpret_raises(IndexError, f, [1]) + except (AssertionError,), e: + pass + else: + assert False + + def f(x): + l = [1] + try: + return l[x] + except IndexError: + return -1 + except Exception: + return 0 + + res = self.interpret(f, [0]) + assert res == 1 + res = self.interpret(f, [1]) + assert res == -1 + + def f(x): + l = [1] + try: + return l[x] + except Exception: + return 0 + + res = self.interpret(f, [0]) + assert res == 1 + res = self.interpret(f, [1]) + assert res == 0 + + def f(x): + l = [1] + try: + return l[x] + except ValueError: + return 0 + + res = self.interpret(f, [0]) + assert res == 1 + try: + self.interpret_raises(IndexError, f, [1]) + except (AssertionError,), e: + pass + else: + assert False + + class TestLLtype(BaseTestRlist, LLRtypeMixin): rlist = ll_rlist Modified: pypy/dist/pypy/rpython/test/test_rstr.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_rstr.py (original) +++ pypy/dist/pypy/rpython/test/test_rstr.py Wed Dec 27 22:23:16 2006 @@ -651,7 +651,62 @@ res = self.interpret(f, [self.string_to_ll("abba")]) assert res - + + def test_getitem_exc(self): + def f(x): + s = "z" + return s[x] + + res = self.interpret(f, [0]) + assert res == 'z' + try: + self.interpret_raises(IndexError, f, [1]) + except (AssertionError,), e: + pass + else: + assert False + + def f(x): + s = "z" + try: + return s[x] + except IndexError: + return 'X' + except Exception: + return ' ' + + res = self.interpret(f, [0]) + assert res == 'z' + res = self.interpret(f, [1]) + assert res == 'X' + + def f(x): + s = "z" + try: + return s[x] + except Exception: + return ' ' + + res = self.interpret(f, [0]) + assert res == 'z' + res = self.interpret(f, [1]) + assert res == ' ' + + def f(x): + s = "z" + try: + return s[x] + except ValueError: + return ' ' + + res = self.interpret(f, [0]) + assert res == 'z' + try: + self.interpret_raises(IndexError, f, [1]) + except (AssertionError,), e: + pass + else: + assert False def FIXME_test_str_to_pystringobj(): def f(n): Modified: pypy/dist/pypy/translator/geninterplevel.py ============================================================================== --- pypy/dist/pypy/translator/geninterplevel.py (original) +++ pypy/dist/pypy/translator/geninterplevel.py Wed Dec 27 22:23:16 2006 @@ -284,8 +284,11 @@ else: fmt = "%s = %s(%s)" # special case is_true - wrapped = op.opname != "is_true" - oper = "space.%s" % op.opname + opname = op.opname + if opname.startswith('getitem_'): + opname = 'getitem' + wrapped = opname != "is_true" + oper = "space.%s" % opname return fmt % (self.expr(op.result, localscope, wrapped), oper, self.arglist(op.args, localscope)) Modified: pypy/dist/pypy/translator/simplify.py ============================================================================== --- pypy/dist/pypy/translator/simplify.py (original) +++ pypy/dist/pypy/translator/simplify.py Wed Dec 27 22:23:16 2006 @@ -288,6 +288,22 @@ traverse(visit, graph) +def transform_xxxitem(graph): + # xxx setitem too + for block in graph.iterblocks(): + if block.operations and block.exitswitch == c_last_exception: + last_op = block.operations[-1] + if last_op.opname == 'getitem': + postfx = [] + for exit in block.exits: + if exit.exitcase is IndexError: + postfx.append('idx') + elif exit.exitcase is KeyError: + postfx.append('key') + if postfx: + last_op.opname = last_op.opname + '_' + '_'.join(postfx) + + def remove_dead_exceptions(graph): """Exceptions can be removed if they are unreachable""" @@ -1039,6 +1055,7 @@ remove_identical_vars, transform_ovfcheck, simplify_exceptions, + transform_xxxitem, remove_dead_exceptions, ] From pedronis at codespeak.net Wed Dec 27 22:31:32 2006 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Wed, 27 Dec 2006 22:31:32 +0100 (CET) Subject: [pypy-svn] r36009 - pypy/dist/pypy/jit Message-ID: <20061227213132.BBA8110084@code0.codespeak.net> Author: pedronis Date: Wed Dec 27 22:31:31 2006 New Revision: 36009 Modified: pypy/dist/pypy/jit/TODO.txt Log: mark the getitem task as in-progress Modified: pypy/dist/pypy/jit/TODO.txt ============================================================================== --- pypy/dist/pypy/jit/TODO.txt (original) +++ pypy/dist/pypy/jit/TODO.txt Wed Dec 27 22:31:31 2006 @@ -1,6 +1,6 @@ - fix the XXXs in codegen -- [] (getitem) used inside complex try/except ends up using the bound +- IN-PROGRESS: [] (getitem) used inside complex try/except ends up using the bound checking version: transformation after flowgraphing that marks op with implicit exceptions only if they are inside a precise try:except: From antocuni at codespeak.net Thu Dec 28 10:46:22 2006 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Thu, 28 Dec 2006 10:46:22 +0100 (CET) Subject: [pypy-svn] r36010 - pypy/dist/pypy/translator/backendopt/test Message-ID: <20061228094622.EB97410086@code0.codespeak.net> Author: antocuni Date: Thu Dec 28 10:46:21 2006 New Revision: 36010 Modified: pypy/dist/pypy/translator/backendopt/test/test_inline.py Log: A failing test Modified: pypy/dist/pypy/translator/backendopt/test/test_inline.py ============================================================================== --- pypy/dist/pypy/translator/backendopt/test/test_inline.py (original) +++ pypy/dist/pypy/translator/backendopt/test/test_inline.py Thu Dec 28 10:46:21 2006 @@ -547,6 +547,7 @@ res = eval_func([]) assert res == 5 + class TestInlineOOType(OORtypeMixin, BaseTestInline): def test_rtype_r_dict_exceptions(self): @@ -570,3 +571,17 @@ res = eval_func([]) assert res == 42 + def test_float(self): + py.test.skip('fixme!') + ex = ['', ' '] + def fn(i): + s = ex[i] + try: + return float(s) + except ValueError: + return -999.0 + + eval_func, t = self.check_auto_inlining(fn, [int]) + expected = fn(0) + res = eval_func([0]) + assert res == expected From arigo at codespeak.net Thu Dec 28 11:40:44 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 28 Dec 2006 11:40:44 +0100 (CET) Subject: [pypy-svn] r36012 - in pypy/dist/pypy: rlib/rctypes rlib/rctypes/test rpython Message-ID: <20061228104044.BC74B10086@code0.codespeak.net> Author: arigo Date: Thu Dec 28 11:40:40 2006 New Revision: 36012 Modified: pypy/dist/pypy/rlib/rctypes/implementation.py pypy/dist/pypy/rlib/rctypes/rstruct.py pypy/dist/pypy/rlib/rctypes/test/test_rprimitive.py pypy/dist/pypy/rpython/controllerentry.py pypy/dist/pypy/rpython/rcontrollerentry.py Log: Turned rtypedelegate() into a more generally useful helper. Use it to pass many of the rtyping tests of test_rprimitive. Modified: pypy/dist/pypy/rlib/rctypes/implementation.py ============================================================================== --- pypy/dist/pypy/rlib/rctypes/implementation.py (original) +++ pypy/dist/pypy/rlib/rctypes/implementation.py Thu Dec 28 11:40:40 2006 @@ -1,6 +1,7 @@ from pypy.annotation import model as annmodel from pypy.rlib.rctypes import rctypesobject from pypy.rpython import extregistry, controllerentry +from pypy.rpython.error import TyperError from pypy.rpython.controllerentry import Controller, ControllerEntry from pypy.rpython.controllerentry import ControllerEntryForPrebuilt from pypy.rpython.controllerentry import SomeControlledInstance @@ -69,12 +70,12 @@ s_obj, s_attr, s_value) def rtype_setattr(self, hop): - r_controlled_instance = hop.args_r[0] + from pypy.rpython.rcontrollerentry import rtypedelegate if s_is_box(hop.args_s[2]): hop2 = revealbox(hop, 2) - return r_controlled_instance.rtypedelegate(self.setboxattr, hop2) + return rtypedelegate(self.setboxattr, hop2) else: - return r_controlled_instance.rtypedelegate(self.setattr, hop) + return rtypedelegate(self.setattr, hop) def ctrl_setitem(self, s_obj, s_key, s_value): if s_is_box(s_value): @@ -85,12 +86,12 @@ s_obj, s_key, s_value) def rtype_setitem(self, hop): - r_controlled_instance = hop.args_r[0] + from pypy.rpython.rcontrollerentry import rtypedelegate if s_is_box(hop.args_s[2]): hop2 = revealbox(hop, 2) - return r_controlled_instance.rtypedelegate(self.setboxitem, hop2) + return rtypedelegate(self.setboxitem, hop2) else: - return r_controlled_instance.rtypedelegate(self.setitem, hop) + return rtypedelegate(self.setitem, hop) class CTypesCallEntry(ControllerEntry): @@ -140,7 +141,8 @@ return s_result def specialize_call(self, hop): - import pdb; pdb.set_trace() + from pypy.rpython.rcontrollerentry import rtypedelegate + return rtypedelegate(controllingfn, hop, revealargs, revealresult) # ____________________________________________________________ # Modified: pypy/dist/pypy/rlib/rctypes/rstruct.py ============================================================================== --- pypy/dist/pypy/rlib/rctypes/rstruct.py (original) +++ pypy/dist/pypy/rlib/rctypes/rstruct.py Thu Dec 28 11:40:40 2006 @@ -18,9 +18,9 @@ fields = [] for name, field_ctype in ctype._fields_: controller = getcontroller(field_ctype) + setattr(self, 'fieldcontroller_' + name, controller) controllers.append((name, controller)) fields.append((name, controller.knowntype)) - self.fieldcontrollers = dict(controllers) external = getattr(ctype, '_external_', False) self.knowntype = rctypesobject.RStruct(ctype.__name__, fields, c_external = external) @@ -29,7 +29,7 @@ # is unrolled unrolled_controllers = unrolling_iterable(controllers) - def new(*args): + def structnew(*args): obj = self.knowntype.allocate() if len(args) > len(fields): raise ValueError("too many arguments for this structure") @@ -41,20 +41,23 @@ controller.set_value(itemobj, value) return obj - self.new = new + self.new = structnew + # Build custom getter and setter methods + def structgetattr(obj, attr): + controller = getattr(self, 'fieldcontroller_' + attr) + itemobj = getattr(obj, 'ref_' + attr)() + return controller.return_value(itemobj) + structgetattr._annspecialcase_ = 'specialize:arg(1)' + + def structsetattr(obj, attr, value): + controller = getattr(self, 'fieldcontroller_' + attr) + itemobj = getattr(obj, 'ref_' + attr)() + controller.set_value(itemobj, value) + structsetattr._annspecialcase_ = 'specialize:arg(1)' - def getattr(self, obj, attr): - controller = self.fieldcontrollers[attr] - itemobj = getattr(obj, 'ref_' + attr)() - return controller.return_value(itemobj) - getattr._annspecialcase_ = 'specialize:arg(2)' - - def setattr(self, obj, attr, value): - controller = self.fieldcontrollers[attr] - itemobj = getattr(obj, 'ref_' + attr)() - controller.set_value(itemobj, value) - setattr._annspecialcase_ = 'specialize:arg(2)' + self.getattr = structgetattr + self.setattr = structsetattr StructCTypeController.register_for_metatype(StructType) Modified: pypy/dist/pypy/rlib/rctypes/test/test_rprimitive.py ============================================================================== --- pypy/dist/pypy/rlib/rctypes/test/test_rprimitive.py (original) +++ pypy/dist/pypy/rlib/rctypes/test/test_rprimitive.py Thu Dec 28 11:40:40 2006 @@ -232,7 +232,7 @@ t.view() -class INPROGRESS_Test_specialization: +class Test_specialization: def test_specialize_c_int(self): def create_c_int(): x = c_int(42) @@ -300,6 +300,7 @@ assert ("%.2f" % res) == ("%.2f" % 4.3) def test_value_for_various_types(self): + py.test.skip("in-progress") def func(): x = c_ushort(5) x.value += 1 @@ -329,6 +330,7 @@ interpret(func, []) def test_convert_from_llvalue(self): + py.test.skip("in-progress") def func(): x = c_ushort(5) pointer(x)[0] += 1 @@ -358,6 +360,7 @@ interpret(func, []) def test_truth_value(self): + py.test.skip("in-progress") bigzero = r_ulonglong(0) big = r_ulonglong(2L**42) def func(n, z): Modified: pypy/dist/pypy/rpython/controllerentry.py ============================================================================== --- pypy/dist/pypy/rpython/controllerentry.py (original) +++ pypy/dist/pypy/rpython/controllerentry.py Thu Dec 28 11:40:40 2006 @@ -43,10 +43,8 @@ return SomeControlledInstance(s_real_obj, controller=self) def rtype_new(self, hop): - r_controlled_instance = hop.r_result - return r_controlled_instance.rtypedelegate(self.new, hop, - revealargs=[], - revealresult=True) + from pypy.rpython.rcontrollerentry import rtypedelegate + return rtypedelegate(self.new, hop, revealargs=[], revealresult=True) def getattr(self, obj, attr): return getattr(self, 'get_' + attr)(obj) @@ -56,8 +54,8 @@ return delegate(self.getattr, s_obj, s_attr) def rtype_getattr(self, hop): - r_controlled_instance = hop.args_r[0] - return r_controlled_instance.rtypedelegate(self.getattr, hop) + from pypy.rpython.rcontrollerentry import rtypedelegate + return rtypedelegate(self.getattr, hop) def setattr(self, obj, attr, value): return getattr(self, 'set_' + attr)(obj, value) @@ -67,22 +65,22 @@ return delegate(self.setattr, s_obj, s_attr, s_value) def rtype_setattr(self, hop): - r_controlled_instance = hop.args_r[0] - return r_controlled_instance.rtypedelegate(self.setattr, hop) + from pypy.rpython.rcontrollerentry import rtypedelegate + return rtypedelegate(self.setattr, hop) def ctrl_getitem(self, s_obj, s_key): return delegate(self.getitem, s_obj, s_key) def rtype_getitem(self, hop): - r_controlled_instance = hop.args_r[0] - return r_controlled_instance.rtypedelegate(self.getitem, hop) + from pypy.rpython.rcontrollerentry import rtypedelegate + return rtypedelegate(self.getitem, hop) def ctrl_setitem(self, s_obj, s_key, s_value): return delegate(self.setitem, s_obj, s_key, s_value) def rtype_setitem(self, hop): - r_controlled_instance = hop.args_r[0] - return r_controlled_instance.rtypedelegate(self.setitem, hop) + from pypy.rpython.rcontrollerentry import rtypedelegate + return rtypedelegate(self.setitem, hop) def delegate(boundmethod, *args_s): Modified: pypy/dist/pypy/rpython/rcontrollerentry.py ============================================================================== --- pypy/dist/pypy/rpython/rcontrollerentry.py (original) +++ pypy/dist/pypy/rpython/rcontrollerentry.py Thu Dec 28 11:40:40 2006 @@ -17,30 +17,6 @@ real_value = self.controller.convert(value) return self.r_real_obj.convert_const(real_value) - def rtypedelegate(self, boundmethod, hop, - revealargs=[0], revealresult=False): - bk = self.rtyper.annotator.bookkeeper - c_meth = Constant(boundmethod) - s_meth = bk.immutablevalue(boundmethod) - hop2 = hop.copy() - for index in revealargs: - s_new, r_new = self.reveal(hop2.args_r[index]) - hop2.args_s[index], hop2.args_r[index] = s_new, r_new - v = hop2.args_v[index] - if isinstance(v, Constant): - real_value = self.controller.convert(v.value) - hop2.args_v[index] = Constant(real_value) - if revealresult: - hop2.s_result, hop2.r_result = self.reveal(hop2.r_result) - hop2.v_s_insertfirstarg(c_meth, s_meth) - hop2.forced_opname = 'simple_call' - return hop2.dispatch() - - def reveal(self, r): - if r is not self: - raise TyperError("expected %r, got %r" % (self, r)) - return self.s_real_obj, self.r_real_obj - def rtype_getattr(self, hop): return self.controller.rtype_getattr(hop) @@ -55,3 +31,31 @@ def rtype_setitem((r_controlled, r_key), hop): return r_controlled.controller.rtype_setitem(hop) + + +def rtypedelegate(callable, hop, revealargs=[0], revealresult=False): + bk = hop.rtyper.annotator.bookkeeper + c_meth = Constant(callable) + s_meth = bk.immutablevalue(callable) + hop2 = hop.copy() + for index in revealargs: + r_controlled = hop2.args_r[index] + if not isinstance(r_controlled, ControlledInstanceRepr): + raise TyperError("args_r[%d] = %r, expected ControlledInstanceRepr" + % (index, r_controlled)) + s_new, r_new = r_controlled.s_real_obj, r_controlled.r_real_obj + hop2.args_s[index], hop2.args_r[index] = s_new, r_new + v = hop2.args_v[index] + if isinstance(v, Constant): + real_value = r_controlled.controller.convert(v.value) + hop2.args_v[index] = Constant(real_value) + if revealresult: + r_controlled = hop2.r_result + if not isinstance(r_controlled, ControlledInstanceRepr): + raise TyperError("r_result = %r, expected ControlledInstanceRepr" + % (r_controlled,)) + s_new, r_new = r_controlled.s_real_obj, r_controlled.r_real_obj + hop2.s_result, hop2.r_result = s_new, r_new + hop2.v_s_insertfirstarg(c_meth, s_meth) + hop2.forced_opname = 'simple_call' + return hop2.dispatch() From arigo at codespeak.net Thu Dec 28 12:58:22 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 28 Dec 2006 12:58:22 +0100 (CET) Subject: [pypy-svn] r36013 - pypy/dist/pypy/rpython Message-ID: <20061228115822.5436310086@code0.codespeak.net> Author: arigo Date: Thu Dec 28 12:58:13 2006 New Revision: 36013 Modified: pypy/dist/pypy/rpython/rpbc.py Log: A simple ll_str() to format error messages involving things like '%s' % (LLTYPE,) Modified: pypy/dist/pypy/rpython/rpbc.py ============================================================================== --- pypy/dist/pypy/rpython/rpbc.py (original) +++ pypy/dist/pypy/rpython/rpbc.py Thu Dec 28 12:58:13 2006 @@ -401,6 +401,13 @@ assert frozendesc is self.frozendesc return object() # lowleveltype is Void + def getstr(self): + return str(self.frozendesc) + getstr._annspecialcase_ = 'specialize:memo' + + def ll_str(self, x): + return self.getstr() + class AbstractMultipleUnrelatedFrozenPBCRepr(CanBeNull, Repr): """For a SomePBC of frozen PBCs that have no common access set. From arigo at codespeak.net Thu Dec 28 12:59:26 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 28 Dec 2006 12:59:26 +0100 (CET) Subject: [pypy-svn] r36014 - in pypy/dist/pypy: rlib/rctypes rlib/rctypes/test rpython Message-ID: <20061228115926.7451410087@code0.codespeak.net> Author: arigo Date: Thu Dec 28 12:59:20 2006 New Revision: 36014 Modified: pypy/dist/pypy/rlib/rctypes/implementation.py pypy/dist/pypy/rlib/rctypes/rprimitive.py pypy/dist/pypy/rlib/rctypes/test/test_rprimitive.py pypy/dist/pypy/rpython/controllerentry.py Log: Fixes in the specialization rules and better SomeImpossibleValue support. Modified: pypy/dist/pypy/rlib/rctypes/implementation.py ============================================================================== --- pypy/dist/pypy/rlib/rctypes/implementation.py (original) +++ pypy/dist/pypy/rlib/rctypes/implementation.py Thu Dec 28 12:59:20 2006 @@ -137,7 +137,8 @@ if revealresult: result_ctype = revealresult(*args_s) controller = getcontroller(result_ctype) - s_result = SomeControlledInstance(s_result, controller) + if s_result != annmodel.s_ImpossibleValue: + s_result = SomeControlledInstance(s_result, controller) return s_result def specialize_call(self, hop): Modified: pypy/dist/pypy/rlib/rctypes/rprimitive.py ============================================================================== --- pypy/dist/pypy/rlib/rctypes/rprimitive.py (original) +++ pypy/dist/pypy/rlib/rctypes/rprimitive.py Thu Dec 28 12:59:20 2006 @@ -37,6 +37,7 @@ CTypeController.__init__(self, ctype) self.VALUETYPE = ctypes_annotation_list[ctype] self.RETTYPE = return_lltype(self.VALUETYPE) + self.is_integer_type = isinstance(self.VALUETYPE, lltype.Number) self.knowntype = rctypesobject.Primitive(self.VALUETYPE) def new(self, *initialvalue): @@ -50,7 +51,6 @@ def initialize_prebuilt(self, obj, x): self.set_value(obj, x.value) - initialize_prebuilt._annspecialcase_ = 'specialize:arg(0)' def get_value(self, obj): llvalue = obj.get_value() @@ -58,8 +58,12 @@ get_value._annspecialcase_ = 'specialize:arg(0)' def set_value(self, obj, value): - if lltype.typeOf(value) != self.RETTYPE: - raise TypeError("'value' must be set to a %s" % (self.RETTYPE,)) + # for integer types, any integer is accepted and silently cast + if not self.is_integer_type: + # otherwise, check that we got the correct type of 'value' + if lltype.typeOf(value) != self.RETTYPE: + raise TypeError("'value' must be set to a %s" % ( + self.RETTYPE,)) llvalue = lltype.cast_primitive(self.VALUETYPE, value) obj.set_value(llvalue) set_value._annspecialcase_ = 'specialize:arg(0)' Modified: pypy/dist/pypy/rlib/rctypes/test/test_rprimitive.py ============================================================================== --- pypy/dist/pypy/rlib/rctypes/test/test_rprimitive.py (original) +++ pypy/dist/pypy/rlib/rctypes/test/test_rprimitive.py Thu Dec 28 12:59:20 2006 @@ -5,7 +5,7 @@ import py.test import pypy.rlib.rctypes.implementation from pypy.annotation.annrpython import RPythonAnnotator -from pypy.translator.translator import TranslationContext +from pypy.annotation import policy from pypy.annotation.model import SomeCTypesObject, SomeObject from pypy import conftest import sys @@ -21,6 +21,15 @@ test_llvm_compile = False class Test_annotation: + def build_types(self, func, argtypes): + P = policy.AnnotatorPolicy() + P.allow_someobjects = False + a = RPythonAnnotator(policy=P) + s = a.build_types(func, argtypes) + if conftest.option.view: + a.translator.view() + return s + def test_simple(self): res = c_int(42) assert res.value == 42 @@ -31,14 +40,9 @@ return res.value - t = TranslationContext() - a = t.buildannotator() - s = a.build_types(func, []) - + s = self.build_types(func, []) assert s.knowntype == int - if conftest.option.view: - t.view() def test_annotate_prebuilt_c_int(self): res = c_int(42) @@ -46,15 +50,9 @@ def func(): return res.value - t = TranslationContext() - a = t.buildannotator() - s = a.build_types(func, []) - + s = self.build_types(func, []) assert s.knowntype == int - if conftest.option.view: - t.view() - def test_annotate_set_c_int_value(self): def func(): res = c_int(42) @@ -62,14 +60,8 @@ return res.value - t = TranslationContext() - a = t.buildannotator() - s = a.build_types(func, []) - + s = self.build_types(func, []) assert s.knowntype == int - - if conftest.option.view: - t.view() def test_annotate_c_double(self): def func(): @@ -77,30 +69,18 @@ return res.value - t = TranslationContext() - a = t.buildannotator() - s = a.build_types(func, []) - + s = self.build_types(func, []) assert s.knowntype == float - if conftest.option.view: - t.view() - def test_annotate_prebuilt_c_double(self): res = c_double(4.2) def func(): return res.value - t = TranslationContext() - a = t.buildannotator() - s = a.build_types(func, []) - + s = self.build_types(func, []) assert s.knowntype == float - if conftest.option.view: - t.view() - def test_annotate_set_c_double_value(self): def func(): res = c_double(4.2) @@ -108,113 +88,65 @@ return res.value - t = TranslationContext() - a = t.buildannotator() - s = a.build_types(func, []) - + s = self.build_types(func, []) assert s.knowntype == float - if conftest.option.view: - t.view() - def test_annotate_primitive_value(self): def func(x): cs = c_short(x) return cs.value - t = TranslationContext() - a = t.buildannotator() - s = a.build_types(func, [int]) - + s = self.build_types(func, [int]) assert s.knowntype == int - - if conftest.option.view: - t.view() def test_annotate_primitive_arrayitem(self): CSA = c_short * 1 def func(x): csa = CSA(x) return csa[0] - t = TranslationContext() - a = t.buildannotator() - s = a.build_types(func, [int]) - + s = self.build_types(func, [int]) assert s.knowntype == int - - if conftest.option.view: - t.view() def test_annotate_primitive_ptritem(self): def func(x): cs = pointer(c_short(x)) return cs[0] - t = TranslationContext() - a = t.buildannotator() - s = a.build_types(func, [int]) - + s = self.build_types(func, [int]) assert s.knowntype == int - if conftest.option.view: - t.view() - def test_annotate_primitive_structfield(self): class S(Structure): _fields_ = [('cs', c_short)] def func(x): s = S(x) return s.cs - t = TranslationContext() - a = t.buildannotator() - s = a.build_types(func, [int]) - + s = self.build_types(func, [int]) assert s.knowntype == int - - if conftest.option.view: - t.view() def test_annotate_set_primitive_value(self): def func(x): cs = c_short() cs.value = x return cs.value - t = TranslationContext() - a = t.buildannotator() - s = a.build_types(func, [int]) - + s = self.build_types(func, [int]) assert s.knowntype == int - if conftest.option.view: - t.view() - def test_annotate_set_primitive_arrayitem(self): CSA = c_short * 1 def func(x): csa = CSA() csa[0] = x return csa[0] - t = TranslationContext() - a = t.buildannotator() - s = a.build_types(func, [int]) - + s = self.build_types(func, [int]) assert s.knowntype == int - - if conftest.option.view: - t.view() def test_annotate_set_primitive_ptritem(self): def func(x): cs = pointer(c_short()) cs[0] = x return cs[0] - t = TranslationContext() - a = t.buildannotator() - s = a.build_types(func, [int]) - + s = self.build_types(func, [int]) assert s.knowntype == int - if conftest.option.view: - t.view() - def test_annotate_set_primitive_structfield(self): class S(Structure): _fields_ = [('cs', c_short)] @@ -222,14 +154,8 @@ s = S() s.cs = x return s.cs - t = TranslationContext() - a = t.buildannotator() - s = a.build_types(func, [int]) - + s = self.build_types(func, [int]) assert s.knowntype == int - - if conftest.option.view: - t.view() class Test_specialization: @@ -300,7 +226,6 @@ assert ("%.2f" % res) == ("%.2f" % 4.3) def test_value_for_various_types(self): - py.test.skip("in-progress") def func(): x = c_ushort(5) x.value += 1 Modified: pypy/dist/pypy/rpython/controllerentry.py ============================================================================== --- pypy/dist/pypy/rpython/controllerentry.py (original) +++ pypy/dist/pypy/rpython/controllerentry.py Thu Dec 28 12:59:20 2006 @@ -3,6 +3,7 @@ from pypy.annotation.bookkeeper import getbookkeeper from pypy.rpython.extregistry import ExtRegistryEntry from pypy.rpython.annlowlevel import cachedtype +from pypy.rpython.error import TyperError class ControllerEntry(ExtRegistryEntry): @@ -16,6 +17,9 @@ return self._controller_() def specialize_call(self, hop): + if hop.s_result == annmodel.s_ImpossibleValue: + raise TyperError("object creation always raises: %s" % ( + hop.spaceop,)) controller = hop.s_result.controller return controller.rtype_new(hop) @@ -40,7 +44,10 @@ def ctrl_new(self, *args_s): s_real_obj = delegate(self.new, *args_s) - return SomeControlledInstance(s_real_obj, controller=self) + if s_real_obj == annmodel.s_ImpossibleValue: + return annmodel.s_ImpossibleValue + else: + return SomeControlledInstance(s_real_obj, controller=self) def rtype_new(self, hop): from pypy.rpython.rcontrollerentry import rtypedelegate @@ -48,7 +55,7 @@ def getattr(self, obj, attr): return getattr(self, 'get_' + attr)(obj) - getattr._annspecialcase_ = 'specialize:arg(2)' + getattr._annspecialcase_ = 'specialize:arg(0, 2)' def ctrl_getattr(self, s_obj, s_attr): return delegate(self.getattr, s_obj, s_attr) @@ -59,7 +66,7 @@ def setattr(self, obj, attr, value): return getattr(self, 'set_' + attr)(obj, value) - setattr._annspecialcase_ = 'specialize:arg(2)' + setattr._annspecialcase_ = 'specialize:arg(0, 2)' def ctrl_setattr(self, s_obj, s_attr, s_value): return delegate(self.setattr, s_obj, s_attr, s_value) From arigo at codespeak.net Thu Dec 28 13:01:05 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 28 Dec 2006 13:01:05 +0100 (CET) Subject: [pypy-svn] r36015 - in pypy/dist/pypy/rlib/rctypes: . test Message-ID: <20061228120105.7424410086@code0.codespeak.net> Author: arigo Date: Thu Dec 28 13:01:02 2006 New Revision: 36015 Modified: pypy/dist/pypy/rlib/rctypes/rpointer.py pypy/dist/pypy/rlib/rctypes/test/test_rprimitive.py Log: Another specialization fix. Modified: pypy/dist/pypy/rlib/rctypes/rpointer.py ============================================================================== --- pypy/dist/pypy/rlib/rctypes/rpointer.py (original) +++ pypy/dist/pypy/rlib/rctypes/rpointer.py Thu Dec 28 13:01:02 2006 @@ -36,6 +36,7 @@ # not supported by ctypes either contentsobj = obj.get_contents() self.contentscontroller.set_value(contentsobj, value) + setitem._annspecialcase_ = 'specialize:arg(0)' PointerCTypeController.register_for_metatype(PointerType) Modified: pypy/dist/pypy/rlib/rctypes/test/test_rprimitive.py ============================================================================== --- pypy/dist/pypy/rlib/rctypes/test/test_rprimitive.py (original) +++ pypy/dist/pypy/rlib/rctypes/test/test_rprimitive.py Thu Dec 28 13:01:02 2006 @@ -255,7 +255,6 @@ interpret(func, []) def test_convert_from_llvalue(self): - py.test.skip("in-progress") def func(): x = c_ushort(5) pointer(x)[0] += 1 From guido at codespeak.net Thu Dec 28 13:02:52 2006 From: guido at codespeak.net (guido at codespeak.net) Date: Thu, 28 Dec 2006 13:02:52 +0100 (CET) Subject: [pypy-svn] r36017 - pypy/dist/pypy/doc/discussion Message-ID: <20061228120252.EFF2210086@code0.codespeak.net> Author: guido Date: Thu Dec 28 13:02:51 2006 New Revision: 36017 Added: pypy/dist/pypy/doc/discussion/build-tool-web-frontend.txt Modified: pypy/dist/pypy/doc/discussion/build-tool-description.txt Log: Updated build tool description doc a bit, added document describing what I have in mind for the web frontend. Modified: pypy/dist/pypy/doc/discussion/build-tool-description.txt ============================================================================== --- pypy/dist/pypy/doc/discussion/build-tool-description.txt (original) +++ pypy/dist/pypy/doc/discussion/build-tool-description.txt Thu Dec 28 13:02:51 2006 @@ -23,24 +23,27 @@ The application consists of 3 main components: a server component, a client component that handles compilations (let's call this a 'participating client') -and a small client component to start compile jobs (which we'll call 'compiling -client' for now). +and a small client component to start compile jobs (which we'll call +'requesting clients' for now). The server waits for participating clients to register, and for compile job requests. When participating clients register, they pass the server information -about what compilations they can handle (system info). Then when a compiling -client requests a compilation job, the server checks whether a binary is -already available, and if so returns that. +about what compilations the system can handle (system info). -If there isn't one, the server walks through a list of connected participating +When now a requesting client requests a compilation job, the server checks +whether a suitable binary is already available, and if so returns that. If +there isn't one, the server walks through a list of connected participating clients to see if one of them can handle the job, and if so dispatches the compilation. If there's no participating client to handle the job, it gets -queued until there is. Also, if a client crashes during compilation, the job -gets re-queued. This process will continue until a suitable build is available. - -Once a build is available, the server will send an email to all email addresses -(it could be that more than one person asked for some build at the same time!) -passed to it by the compiling clients. +queued until there is. If a client crashes during compilation, the build is +restarted, or error information is sent to the logs and requesting client, +depending on the type of error. As long as no compilation error occurs (read: +on disconnects, system errors, etc.) compilation will be retried until a +build is available. + +Once a build is available, the server will send an email to all clients waiting +for the build (it could be that more than one person asked for some build at +the same time!). Configuration ============= @@ -48,47 +51,55 @@ There are several aspects to configuration on this system. Of course, for the server, client and startcompile components there is configuration for the host and port to connect to, and there is some additional configuration for things -like which mailhost to use (only applies to the server), but also there are -configurations passed around to determine what client is picked, and what the -client needs to compile exactly. - -Application configuration -------------------------- - -The 'host and port configuration' as dicussed in the previous paragraph, for -all components this can be found in 'pypy/tool/build/config.py'. Unless you are -using a test version of the build tool, participate in a project that is not -PyPy, or want to do testing yourself, this should generally be left alone. +like which mailhost to use (only applies to the server), but also there is +configuration data passed around to determine what client is picked, and what +the client needs to compile exactly. + +Config file +----------- + +The host/port configuration etc. can be found in the file 'config.py' in the +build tool dir. There are several things that can be configured here, mostly +related to what application to build, and where to build it. Please read the +file carefully when setting up a new build network, or when participating for +compilation, because certain items (e.g. the svnpath_to_url function, or the +client_checkers) can make the system a lot less secure when not configured +properly. + +Note that all client-related configuration is done from command-line switches, +so the configuration file is supposed to be changed on a per-project basis: +unless you have specific needs, use a test version of the build tool, or are +working on another project than PyPy, you will not want to modify the it. System configuration -------------------- This information is used by the client and startcompile components. On the participating clients this information is retrieved by querying the system, on -the compiling clients the system values are used by default, but may be -overridden (so a compiling client running an x86 can still request PPC builds, -for instance). The server finds a matching participant client for a certain -compilation request by determining if the provided compilation system -configuration is a subset of that provided by participating clients. Note that -the version of the source code (either the release number or SVN revision) -is a special part of this configuration, the participating clients tell what -PyPy versions they can provide, the compiling clients give a range of versions -that it doesn't mind getting (XXX not sure if I agree here, I think having the -participating clients 'svn switch' for each compilation makes more sense...) +the requesting clients the system values are used by default, but may be +overridden (so a requesting client running an x86 can still request PPC builds, +for instance). The clients compare their own system config to that of a build +request, and will (should) refuse a build if it can not be executed because +of incompatibilities. Compilation configuration ------------------------- The third form of configuration is that of the to-be-built application itself, its compilation arguments. This configuration is only provided by the -compiling clients, assumed is that participating clients can deal with any -application configuration. (XXX oops, this is not by default true, is it? -For instance, not all modules can be built on all systems, depending on which -libraries are installed, right? Or can we deal with that through system -config somehow?) - -Compilation configuration can be controlled using command-line arguments (use -'--help' for an overview). +requesting clients, participating clients can examine the information and +refuse a compilation based on this configuration (just like with the system +config, see 'client_checkers' in 'config.py'). Compilation configuration can be +controlled using command-line arguments (use 'bin/startcompile --help' for an +overview). + +Build tool options +------------------ + +Yet another part of the configuration are the options that can be passed to +the 'request a build' script, the requesting client can specify what SVN path +(relative to a certain base path) and what Subversion revision is desired. +The revision can either be specified exactly, or as a range of versions. Installation ============ @@ -105,16 +116,64 @@ Also for the server there's no real setup required, and again there's a dependency on the `py lib`_. Starting it is done by running './bin/server'. -.. _`py lib`: http://codespeak.net/py - Running a compile job --------------------- Again installation is not required, just run './bin/startcompile [options] -' (see --help for the options) to start. +' (see --help for the options) to start. Again, you need to have the +`py lib`_ installed. + +.. _`py lib`: http://codespeak.net/py + +Using the build tool for other projects +======================================= + +The code for the build tool is meant to be generic. Using it for other projects +than PyPy (for which it was originally written) is relatively straight-forward: +just change the configuration, and implement a build client script (probably +highly resembling bin/client). + +Prerequisities +-------------- + +Your project can use the build tool if: + + * it can be built from Python + + Of course this is a rather vague requirement: theoretically _anything_ can + be built from Python; it's just a matter of integrating it into the tool + properly... A project that can entirely be built from Python code (like + PyPy) is easier to integrate than something that is built from the command + line, though (although implementing that won't be very hard either). + + * it is located in Subversion + + The build tool makes very little hard-coded assumptions, but having code + in Subversion is one of them. There are several locations in the code where + SVN is assumed: the command line options (see `build tool options`_), + the server (which checks SVN urls for validity, and converts HEAD revision + requests to actual revision ids) and and build client (which checks out the + data) all make this assumption, changing to a different revision control + system is currently not easy and unsupported (but who knows what the future + will bring). + + * it uses PyPy's config mechanism + + PyPy has a very nice, generic configuration mechanism (essentially wrapper + OptionParser stuff) that makes dealing with fragmented configuration + and command-line options a lot easier. This mechanism is used by the build + tool: it assumes configuration is provided in this format. If your project + uses this configuration mechanism already, you can provide the root Config + object from config.compile_config; if not it should be fairly straight- + forward to wrap your existing configuration with the PyPy stuff. + +Basically that's it: if your project is stored in SVN, and you don't mind using +Python a bit, it shouldn't be too hard to get things going (note that more +documentation about this subject will follow in the future). More info ========= For more information, bug reports, patches, etc., please send an email to guido at merlinux.de. + Added: pypy/dist/pypy/doc/discussion/build-tool-web-frontend.txt ============================================================================== --- (empty file) +++ pypy/dist/pypy/doc/discussion/build-tool-web-frontend.txt Thu Dec 28 13:02:51 2006 @@ -0,0 +1,94 @@ +======================== +Build tool web frontend +======================== + +What is it? +============ + +This document describes the web front-end for the 'build tool' that is part of +the PyPy package, and used to compile PyPy on clients that participate in the +PyPy build network. Both the build tool and this web front-end are generic, so +they can be used for other projects too. + +See `build-tool-description.txt`_ for more details about the tool itself. + +.. _`build-tool-description.txt`: build-tool-description.txt + +Overview +========= + +The front-end consists of a single page, and uses XMLHttpRequest to communicate +with the server. It presents a form that lets the user provide: + + * an email address + + this to send mail to when a build is done, or has failed + + * system information + + certain specifications of the system the build will run on, such as the + operating system and cpu type + + * compilation options + + the features the build should contain + + * svn revision/range + + what svn revision to use, optionally with a range that specifies which + other revisions are allowed + +Once the user has filled in the form, the information is sent to the server +where it is validated. If validation is not successful, a message is sent to +the client about what fields need to be filled in, or clash (certain +compilation options can clash); the user can modify the form and re-submit. If +validation succeeds, a build is requested, which can either result in a URL +returned (if a build is already available) or a message about whether a build +is already in progress, or if the request is queued instead. + +Technical details +================== + +The form is a single static HTML page, that is blank when the user enters the +page. The client then requests (using XMLHttpRequest) the form fields that are +not static (system information + compilation options, email and svn info are +hard-coded in the form), and presents them (using JavaScript that is generated +from RPython using PyPy). The user can now fill in the form, when done it can +press 'submit' to send the form contents to the server (again using XHR) for +validation and (if validation is successful) execution. The results are sent +back to the client and presented to the user: if it consists of validation +error information it is presented in the form (as red fields or something), +if it's a url it is presented as a download, and if it's a message it's +alerted. + +Notes +====== + +Some random notes about implementation: + + * If this was a 'personal project', I would have used some simple templating + language I wrote myself (`Templess`_), but to not depend on some external + lib, and to make it easier for others to work with this (or is it?) I + decided to work with static HTML that is filled with JSON data from JS + instead... Not sure if it indeed works out well, who knows at some point + we may decide to use a templating language of some sort (you probably + guess which I'd vote for ;) after all... Another option would be + py.xml.html, although I don't like having to deal with presentation details + from code too much... + + * The first idea I had for this application was to use + pypy.translator.js.examples.web for the web server, which provides + transparent XMLHttpRequest and JSON functionality... However, because this + is rather ad-hoc, and doesn't seem suitable for production situations, + I decided that was not a good idea... Making it more suitable for + production doesn't seem like an easy task (currently it uses + BaseHTTPServer for instance), although very tempting, since this can imo + become one of the most interesting web application frameworks available... + If this would be made solid and more usable (read: more docs and a cleaner, + higher level API), especially after adding features like transparent + session handling, better HTTP support and more browser abstractions, it + can make development of larger web applications that use 'AJAX' + (XMLHttpRequest, perhaps with some XML) a lot easier, I think... + +.. _`Templess`: http://templess.johnnydebris.net/ + From arigo at codespeak.net Thu Dec 28 13:12:14 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 28 Dec 2006 13:12:14 +0100 (CET) Subject: [pypy-svn] r36018 - in pypy/dist/pypy: rlib/rctypes rlib/rctypes/test rpython Message-ID: <20061228121214.BF8C610086@code0.codespeak.net> Author: arigo Date: Thu Dec 28 13:12:12 2006 New Revision: 36018 Modified: pypy/dist/pypy/rlib/rctypes/rprimitive.py pypy/dist/pypy/rlib/rctypes/test/test_rprimitive.py pypy/dist/pypy/rpython/controllerentry.py pypy/dist/pypy/rpython/rcontrollerentry.py Log: - is_true support. - fix float support. Modified: pypy/dist/pypy/rlib/rctypes/rprimitive.py ============================================================================== --- pypy/dist/pypy/rlib/rctypes/rprimitive.py (original) +++ pypy/dist/pypy/rlib/rctypes/rprimitive.py Thu Dec 28 13:12:12 2006 @@ -37,7 +37,7 @@ CTypeController.__init__(self, ctype) self.VALUETYPE = ctypes_annotation_list[ctype] self.RETTYPE = return_lltype(self.VALUETYPE) - self.is_integer_type = isinstance(self.VALUETYPE, lltype.Number) + self.is_char_type = self.VALUETYPE in (lltype.Char, lltype.UniChar) self.knowntype = rctypesobject.Primitive(self.VALUETYPE) def new(self, *initialvalue): @@ -58,9 +58,9 @@ get_value._annspecialcase_ = 'specialize:arg(0)' def set_value(self, obj, value): - # for integer types, any integer is accepted and silently cast - if not self.is_integer_type: - # otherwise, check that we got the correct type of 'value' + # for integer and float types, any integer is accepted and silently + # cast. For char types, do a precise check + if self.is_char_type: if lltype.typeOf(value) != self.RETTYPE: raise TypeError("'value' must be set to a %s" % ( self.RETTYPE,)) @@ -72,6 +72,13 @@ # they are returned by most operations return_value = get_value + def is_true(self, obj): + llvalue = self.get_value(obj) + if self.is_char_type: + llvalue = ord(llvalue) + return bool(llvalue) + is_true._annspecialcase_ = 'specialize:arg(0)' + for _ctype in ctypes_annotation_list: PrimitiveCTypeController.register_for_type(_ctype) Modified: pypy/dist/pypy/rlib/rctypes/test/test_rprimitive.py ============================================================================== --- pypy/dist/pypy/rlib/rctypes/test/test_rprimitive.py (original) +++ pypy/dist/pypy/rlib/rctypes/test/test_rprimitive.py Thu Dec 28 13:12:12 2006 @@ -284,7 +284,6 @@ interpret(func, []) def test_truth_value(self): - py.test.skip("in-progress") bigzero = r_ulonglong(0) big = r_ulonglong(2L**42) def func(n, z): Modified: pypy/dist/pypy/rpython/controllerentry.py ============================================================================== --- pypy/dist/pypy/rpython/controllerentry.py (original) +++ pypy/dist/pypy/rpython/controllerentry.py Thu Dec 28 13:12:12 2006 @@ -89,6 +89,13 @@ from pypy.rpython.rcontrollerentry import rtypedelegate return rtypedelegate(self.setitem, hop) + def ctrl_is_true(self, s_obj): + return delegate(self.is_true, s_obj) + + def rtype_is_true(self, hop): + from pypy.rpython.rcontrollerentry import rtypedelegate + return rtypedelegate(self.is_true, hop) + def delegate(boundmethod, *args_s): bk = getbookkeeper() @@ -124,6 +131,9 @@ assert s_attr.is_constant() s_cin.controller.ctrl_setattr(s_cin.s_real_obj, s_attr, s_value) + def is_true(s_cin): + return s_cin.controller.ctrl_is_true(s_cin.s_real_obj) + class __extend__(pairtype(SomeControlledInstance, annmodel.SomeObject)): Modified: pypy/dist/pypy/rpython/rcontrollerentry.py ============================================================================== --- pypy/dist/pypy/rpython/rcontrollerentry.py (original) +++ pypy/dist/pypy/rpython/rcontrollerentry.py Thu Dec 28 13:12:12 2006 @@ -23,6 +23,9 @@ def rtype_setattr(self, hop): return self.controller.rtype_setattr(hop) + def rtype_is_true(self, hop): + return self.controller.rtype_is_true(hop) + class __extend__(pairtype(ControlledInstanceRepr, Repr)): From ericvrp at codespeak.net Thu Dec 28 14:18:18 2006 From: ericvrp at codespeak.net (ericvrp at codespeak.net) Date: Thu, 28 Dec 2006 14:18:18 +0100 (CET) Subject: [pypy-svn] r36019 - in pypy/dist/pypy/jit/codegen/llvm: . lib test Message-ID: <20061228131818.BAAA710090@code0.codespeak.net> Author: ericvrp Date: Thu Dec 28 14:18:14 2006 New Revision: 36019 Modified: pypy/dist/pypy/jit/codegen/llvm/lib/libllvmjit.cpp pypy/dist/pypy/jit/codegen/llvm/llvmjit.py pypy/dist/pypy/jit/codegen/llvm/rgenop.py pypy/dist/pypy/jit/codegen/llvm/test/test_genc_ts.py pypy/dist/pypy/jit/codegen/llvm/test/test_llvmjit.py pypy/dist/pypy/jit/codegen/llvm/test/test_operation.py pypy/dist/pypy/jit/codegen/llvm/test/test_rgenop.py Log: Make most jit/codegen/llvm test pass with llvm 1.9 too. Skip those that have know issues. Modified: pypy/dist/pypy/jit/codegen/llvm/lib/libllvmjit.cpp ============================================================================== --- pypy/dist/pypy/jit/codegen/llvm/lib/libllvmjit.cpp (original) +++ pypy/dist/pypy/jit/codegen/llvm/lib/libllvmjit.cpp Thu Dec 28 14:18:14 2006 @@ -74,7 +74,7 @@ PassManager passes; passes.add(new TargetData(gp_module)); // some passes need this as a first pass - passes.add(createVerifierPass()); // Make sure we start with a good graph + passes.add(createVerifierPass(PrintMessageAction)); // Make sure we start with a good graph //passes.add(new PrintModulePass()); // Visual feedback if (optLevel >= 1) { @@ -143,7 +143,7 @@ // Compile silly sequences passes.add(createInstructionCombiningPass()); // Make sure everything is still good. - passes.add(createVerifierPass()); + passes.add(createVerifierPass(PrintMessageAction)); //passes.add(new PrintModulePass()); // Visual feedback return passes.run(*gp_module); Modified: pypy/dist/pypy/jit/codegen/llvm/llvmjit.py ============================================================================== --- pypy/dist/pypy/jit/codegen/llvm/llvmjit.py (original) +++ pypy/dist/pypy/jit/codegen/llvm/llvmjit.py Thu Dec 28 14:18:14 2006 @@ -44,6 +44,14 @@ libraries = (os.path.join(os.path.dirname(path), 'llvmjit'),) llvmjit._FuncPtr = _FuncPtr +MINIMAL_VERSION = 2.0 + +def llvm_version(): + v = os.popen('llvm-as -version 2>&1').read() + v = ''.join([c for c in v if c.isdigit()]) + v = int(v) / 10.0 + return v + #ensure stable state (XXX this doesn't seem to get called when translated! We do it in parse!) llvmjit.restart() Modified: pypy/dist/pypy/jit/codegen/llvm/rgenop.py ============================================================================== --- pypy/dist/pypy/jit/codegen/llvm/rgenop.py (original) +++ pypy/dist/pypy/jit/codegen/llvm/rgenop.py Thu Dec 28 14:18:14 2006 @@ -20,14 +20,19 @@ WORD = 4 +llvm2 = llvmjit.llvm_version() >= 2.0 -MINIMAL_VERSION = 2.0 +if llvm2: + icmp = 'icmp ' + scmp = 'icmp s' + ucmp = 'icmp u' + fcmp = 'fcmp o' +else: + icmp = scmp = ucmp = fcmp = 'set' -def llvm_version(): - v = os.popen('llvm-as -version 2>&1').read() - v = ''.join([c for c in v if c.isdigit()]) - v = int(v) / 10.0 - return v + +class ParseException(Exception): + pass class Logger: @@ -422,25 +427,54 @@ def op_float_truediv(self, gv_x, gv_y): return self._rgenop2_generic('fdiv', gv_x, gv_y) def op_float_neg(self, gv_x): return self._rgenop2_generic('sub', FloatConst(0.0), gv_x) - def op_int_lt(self, gv_x, gv_y): return self._rgenop2_generic('icmp slt', gv_x, gv_y, 'bool') - def op_int_le(self, gv_x, gv_y): return self._rgenop2_generic('icmp sle', gv_x, gv_y, 'bool') - def op_int_eq(self, gv_x, gv_y): return self._rgenop2_generic('icmp eq' , gv_x, gv_y, 'bool') - def op_int_ne(self, gv_x, gv_y): return self._rgenop2_generic('icmp ne' , gv_x, gv_y, 'bool') - def op_int_gt(self, gv_x, gv_y): return self._rgenop2_generic('icmp sgt', gv_x, gv_y, 'bool') - def op_int_ge(self, gv_x, gv_y): return self._rgenop2_generic('icmp sge', gv_x, gv_y, 'bool') - - def op_uint_lt(self, gv_x, gv_y): return self._rgenop2_generic('icmp ult', gv_x, gv_y, 'bool') - def op_uint_le(self, gv_x, gv_y): return self._rgenop2_generic('icmp ule', gv_x, gv_y, 'bool') - def op_uint_gt(self, gv_x, gv_y): return self._rgenop2_generic('icmp ugt', gv_x, gv_y, 'bool') - def op_uint_ge(self, gv_x, gv_y): return self._rgenop2_generic('icmp uge', gv_x, gv_y, 'bool') - - def op_float_lt(self, gv_x, gv_y): return self._rgenop2_generic('fcmp olt', gv_x, gv_y, 'bool') - def op_float_le(self, gv_x, gv_y): return self._rgenop2_generic('fcmp ole', gv_x, gv_y, 'bool') - def op_float_eq(self, gv_x, gv_y): return self._rgenop2_generic('fcmp oeq', gv_x, gv_y, 'bool') - def op_float_ne(self, gv_x, gv_y): return self._rgenop2_generic('fcmp one', gv_x, gv_y, 'bool') - def op_float_gt(self, gv_x, gv_y): return self._rgenop2_generic('fcmp ogt', gv_x, gv_y, 'bool') - def op_float_ge(self, gv_x, gv_y): return self._rgenop2_generic('fcmp oge', gv_x, gv_y, 'bool') + def op_int_lt(self, gv_x, gv_y): + return self._rgenop2_generic(scmp + 'lt', gv_x, gv_y, 'bool') + + def op_int_le(self, gv_x, gv_y): + return self._rgenop2_generic(scmp + 'le', gv_x, gv_y, 'bool') + + def op_int_eq(self, gv_x, gv_y): + return self._rgenop2_generic(icmp + 'eq' , gv_x, gv_y, 'bool') + + def op_int_ne(self, gv_x, gv_y): + return self._rgenop2_generic(icmp + 'ne' , gv_x, gv_y, 'bool') + + def op_int_gt(self, gv_x, gv_y): + return self._rgenop2_generic(scmp + 'gt', gv_x, gv_y, 'bool') + + def op_int_ge(self, gv_x, gv_y): + return self._rgenop2_generic(scmp + 'ge', gv_x, gv_y, 'bool') + + def op_uint_lt(self, gv_x, gv_y): + return self._rgenop2_generic(ucmp + 'lt', gv_x, gv_y, 'bool') + + def op_uint_le(self, gv_x, gv_y): + return self._rgenop2_generic(ucmp + 'le', gv_x, gv_y, 'bool') + def op_uint_gt(self, gv_x, gv_y): + return self._rgenop2_generic(ucmp + 'gt', gv_x, gv_y, 'bool') + + def op_uint_ge(self, gv_x, gv_y): + return self._rgenop2_generic(ucmp + 'ge', gv_x, gv_y, 'bool') + + def op_float_lt(self, gv_x, gv_y): + return self._rgenop2_generic(fcmp + 'lt', gv_x, gv_y, 'bool') + + def op_float_le(self, gv_x, gv_y): + return self._rgenop2_generic(fcmp + 'le', gv_x, gv_y, 'bool') + + def op_float_eq(self, gv_x, gv_y): + return self._rgenop2_generic(fcmp + 'eq', gv_x, gv_y, 'bool') + + def op_float_ne(self, gv_x, gv_y): + return self._rgenop2_generic(fcmp + 'ne', gv_x, gv_y, 'bool') + + def op_float_gt(self, gv_x, gv_y): + return self._rgenop2_generic(fcmp + 'gt', gv_x, gv_y, 'bool') + + def op_float_ge(self, gv_x, gv_y): + return self._rgenop2_generic(fcmp + 'ge', gv_x, gv_y, 'bool') + op_unichar_eq = op_ptr_eq = op_uint_eq = op_int_eq op_unichar_ne = op_ptr_ne = op_uint_ne = op_int_ne @@ -469,9 +503,9 @@ gv_abs_pos = Var(gv_x.type) gv_result = Var(gv_x.type) if nullstr is '0': - l = ' %s=icmp sge %s,%s' + l = ' %s=' + scmp + 'ge %s,%s' else: - l = ' %s=fcmp oge %s,%s' + l = ' %s=' + fcmp + 'ge %s,%s' self.asm.append(l % (gv_comp.operand2(), gv_x.operand(), nullstr)) self.asm.append(' %s=sub %s %s,%s' % ( gv_abs_pos.operand2(), gv_x.type, nullstr, gv_x.operand2())) @@ -611,9 +645,9 @@ log('%s Builder._is_false %s' % (self.block.label, gv_x.operand())) gv_result = Var('bool') if nullstr is '0': - l = ' %s=icmp eq %s,%s' + l = ' %s=' + icmp + 'eq %s,%s' else: - l = ' %s=fcmp oeq %s,%s' + l = ' %s=' + fcmp + 'eq %s,%s' self.asm.append(l % (gv_result.operand2(), gv_x.operand(), nullstr)) return gv_result @@ -621,9 +655,9 @@ log('%s Builder._is_true %s' % (self.block.label, gv_x.operand())) gv_result = Var('bool') if nullstr is '0': - l = ' %s=icmp ne %s,%s' + l = ' %s=' + icmp + 'ne %s,%s' else: - l = ' %s=fcmp one %s,%s' + l = ' %s=' + fcmp + 'ne %s,%s' self.asm.append(l % (gv_result.operand2(), gv_x.operand(), nullstr)) return gv_result @@ -864,7 +898,9 @@ if PRINT_SOURCE: print asm_string logger.dump(asm_string) - llvmjit.parse(asm_string) + parse_ok = llvmjit.parse(asm_string) + if not parse_ok: + raise ParseException() llvmjit.transform(3) #optimize module (should be on functions actually) function = llvmjit.getNamedFunction(self.name) entrypoint = llvmjit.getPointerToFunctionAsInt(function) 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 Dec 28 14:18:14 2006 @@ -1,7 +1,8 @@ import py from pypy.jit.codegen.i386.test.test_genc_ts import I386TimeshiftingTestMixin from pypy.jit.timeshifter.test import test_timeshift -from pypy.jit.codegen.llvm.rgenop import RLLVMGenOp, llvm_version, MINIMAL_VERSION +from pypy.jit.codegen.llvm.rgenop import RLLVMGenOp +from pypy.jit.codegen.llvm.llvmjit import llvm_version, MINIMAL_VERSION skip_passing = False Modified: pypy/dist/pypy/jit/codegen/llvm/test/test_llvmjit.py ============================================================================== --- pypy/dist/pypy/jit/codegen/llvm/test/test_llvmjit.py (original) +++ pypy/dist/pypy/jit/codegen/llvm/test/test_llvmjit.py Thu Dec 28 14:18:14 2006 @@ -26,18 +26,19 @@ }''' # -lldeadcode = '''int %deadcode(int %n) { +llvm2 = llvmjit.llvm_version() >= 2.0 +lldeadcode = '''int %%deadcode(int %%n) { Test: - %cond = icmp eq int %n, %n - br bool %cond, label %IfEqual, label %IfUnequal + %%cond = %s int %%n, %%n + br bool %%cond, label %%IfEqual, label %%IfUnequal IfEqual: - %n2 = mul int %n, 2 - ret int %n2 + %%n2 = mul int %%n, 2 + ret int %%n2 IfUnequal: ret int -1 -}''' +}''' % ('seteq', 'icmp eq')[llvm2] # llfuncA = '''int %func(int %n) { Modified: pypy/dist/pypy/jit/codegen/llvm/test/test_operation.py ============================================================================== --- pypy/dist/pypy/jit/codegen/llvm/test/test_operation.py (original) +++ pypy/dist/pypy/jit/codegen/llvm/test/test_operation.py Thu Dec 28 14:18:14 2006 @@ -1,7 +1,8 @@ import py from pypy.jit.codegen.llvm.test.test_llvmjit import skip_unsupported_platform from pypy.jit.codegen.i386.test.test_operation import BasicTests -from pypy.jit.codegen.llvm.rgenop import RLLVMGenOp, llvm_version, MINIMAL_VERSION +from pypy.jit.codegen.llvm.rgenop import RLLVMGenOp +from pypy.jit.codegen.llvm.llvmjit import llvm_version, MINIMAL_VERSION class LLVMTestBasicMixin(object): @@ -21,7 +22,7 @@ py.test.skip('found llvm %.1f, requires at least llvm %.1f(cvs)' % ( llvm_version(), MINIMAL_VERSION)) - if llvm_version() < MINIMAL_VERSION: + if llvm_version() < 2.0: test_arithmetic = skip_too_minimal test_comparison = skip_too_minimal test_char_comparison = skip_too_minimal Modified: pypy/dist/pypy/jit/codegen/llvm/test/test_rgenop.py ============================================================================== --- pypy/dist/pypy/jit/codegen/llvm/test/test_rgenop.py (original) +++ pypy/dist/pypy/jit/codegen/llvm/test/test_rgenop.py Thu Dec 28 14:18:14 2006 @@ -1,5 +1,6 @@ import py -from pypy.jit.codegen.llvm.rgenop import RLLVMGenOp, llvm_version, MINIMAL_VERSION +from pypy.jit.codegen.llvm.rgenop import RLLVMGenOp +from pypy.jit.codegen.llvm.llvmjit import llvm_version, MINIMAL_VERSION from pypy.jit.codegen.test.rgenop_tests import AbstractRGenOpTests from sys import platform From guido at codespeak.net Thu Dec 28 14:43:50 2006 From: guido at codespeak.net (guido at codespeak.net) Date: Thu, 28 Dec 2006 14:43:50 +0100 (CET) Subject: [pypy-svn] r36020 - in pypy/dist/pypy/tool/build: . bin test Message-ID: <20061228134350.4B24B10090@code0.codespeak.net> Author: guido Date: Thu Dec 28 14:43:47 2006 New Revision: 36020 Modified: pypy/dist/pypy/tool/build/bin/client pypy/dist/pypy/tool/build/build.py pypy/dist/pypy/tool/build/client.py pypy/dist/pypy/tool/build/config.py pypy/dist/pypy/tool/build/test/test_build.py Log: Added a .error attribute on BuildPath, which contains an instance of the type of error that has occurred on the client (can be used for more advanced error handling later). Also some small cleanups, and fixed a path in the config. Modified: pypy/dist/pypy/tool/build/bin/client ============================================================================== --- pypy/dist/pypy/tool/build/bin/client (original) +++ pypy/dist/pypy/tool/build/bin/client Thu Dec 28 14:43:47 2006 @@ -82,3 +82,4 @@ from pypy.tool.build.client import main main(config, path, compile) + Modified: pypy/dist/pypy/tool/build/build.py ============================================================================== --- pypy/dist/pypy/tool/build/build.py (original) +++ pypy/dist/pypy/tool/build/build.py Thu Dec 28 14:43:47 2006 @@ -36,7 +36,7 @@ progress """ - + def _request(self): req = self.join('request') if not req.check(): @@ -77,6 +77,25 @@ return not not self.log done = property(_done) + _reg_error = py.std.re.compile(r'uring compilation:\n([^:]+): (.*)') + def _error(self): + if self.done and not self.zipfile.size(): + log = self.log + match = self._reg_error.search(log) + if not match: + return Exception + exc = match.group(1) + msg = match.group(2) + try: + exc = eval('%s(%r)' % (exc, msg)) + except Exception, e: + print e + exc = Exception('%s: %s' % (exc, msg)) + return exc + return None + + error = property(_error) + class BuildRequest(object): """ build request data Modified: pypy/dist/pypy/tool/build/client.py ============================================================================== --- pypy/dist/pypy/tool/build/client.py (original) +++ pypy/dist/pypy/tool/build/client.py Thu Dec 28 14:43:47 2006 @@ -44,7 +44,8 @@ try: chunk = self.channel.receive() except EOFError: - # stop compilation, client has disconnected + # stop compilation, client has disconnected (server + # will check the connection after a while and clean up) return # end of data is marked by sending a None if chunk is None: Modified: pypy/dist/pypy/tool/build/config.py ============================================================================== --- pypy/dist/pypy/tool/build/config.py (original) +++ pypy/dist/pypy/tool/build/config.py Thu Dec 28 14:43:47 2006 @@ -28,10 +28,10 @@ buildpath = packageparent.ensure('/pypy/tool/build/builds', dir=True) mailhost = 'localhost' mailport = 25 -mailfrom = 'pypybuilds at codespeak.net' +mailfrom = 'guido at codespeak.net' # settings for the tests -testpath = [str(py.magic.autopath().dirpath().dirpath())] +testpath = [str(py.magic.autopath().dirpath().dirpath().dirpath().dirpath())] # this var is only used below svnroot = 'http://codespeak.net/svn/pypy' Modified: pypy/dist/pypy/tool/build/test/test_build.py ============================================================================== --- pypy/dist/pypy/tool/build/test/test_build.py (original) +++ pypy/dist/pypy/tool/build/test/test_build.py Thu Dec 28 14:43:47 2006 @@ -151,3 +151,31 @@ testurl + '/baz', 1, 0) assert not br8.has_satisfying_data(br1) +def test_buildrequest_error(): + tempdir = py.test.ensuretemp('pypybuilder-buildpath') + bp = build.BuildPath(str(tempdir / 'test_error')) + assert bp.error is None + bp.log = """ +============================================================================== +Exception during compilation: +SyntaxError: foo +... +traceback here +... +============================================================================== +""" + e = bp.error + assert e.__class__ == SyntaxError + assert str(e) == 'foo' + bp.log = """ +============================================================================== +Exception during compilation: +FooBarException: baz +... +traceback here +... +""" + e = bp.error + assert e.__class__ == Exception + assert str(e) == 'FooBarException: baz' + From pedronis at codespeak.net Thu Dec 28 14:59:19 2006 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Thu, 28 Dec 2006 14:59:19 +0100 (CET) Subject: [pypy-svn] r36021 - pypy/dist/pypy/jit/timeshifter Message-ID: <20061228135919.17E1610090@code0.codespeak.net> Author: pedronis Date: Thu Dec 28 14:59:16 2006 New Revision: 36021 Modified: pypy/dist/pypy/jit/timeshifter/transform.py Log: use a subclass of GraphAnalyzer (which does caching) to distinguish green/yellow calls. special case 'debug_assert' to be ignored. Modified: pypy/dist/pypy/jit/timeshifter/transform.py ============================================================================== --- pypy/dist/pypy/jit/timeshifter/transform.py (original) +++ pypy/dist/pypy/jit/timeshifter/transform.py Thu Dec 28 14:59:16 2006 @@ -3,15 +3,30 @@ from pypy.annotation import model as annmodel from pypy.jit.hintannotator import model as hintmodel from pypy.jit.hintannotator.model import originalconcretetype -from pypy.rpython.lltypesystem import lltype, llmemory +from pypy.rpython.lltypesystem import lltype, llmemory, lloperation from pypy.rpython.rmodel import inputconst from pypy.translator.unsimplify import varoftype, copyvar from pypy.translator.unsimplify import split_block, split_block_at_start -from pypy.translator.simplify import rec_op_has_side_effects +#from pypy.translator.simplify import rec_op_has_side_effects +from pypy.translator.backendopt import graphanalyze from pypy.translator.backendopt.ssa import SSA_to_SSI from pypy.translator.unsimplify import split_block +class HasSideeffects(graphanalyze.GraphAnalyzer): + + EXCEPTIONS = ('debug_assert',) + + def analyze_exceptblock(self, block, seen=None): + # graphs explicitly raising have side-effects + return True + + def operation_is_true(self, op): + opname = op.opname + return (lloperation.LL_OPERATIONS[opname].sideeffects and + opname not in self.EXCEPTIONS) + + class MergePointFamily(object): def __init__(self, tsgraph): self.tsgraph = tsgraph @@ -48,6 +63,12 @@ self.c_mpfamily = inputconst(lltype.Void, self.mergepointfamily) self.tsgraphs_seen = [] + t = self.hannotator.base_translator + self.sideeffects_analyzer = HasSideeffects(t) + + def has_sideeffects(self, op): + return self.sideeffects_analyzer.analyze(op) + def transform(self): self.compute_merge_points() self.insert_save_return() @@ -475,8 +496,7 @@ if hs_res.is_green(): # all-green arguments and result. # Does the function have side-effects? - t = self.hannotator.base_translator - if not rec_op_has_side_effects(t, spaceop): + if not self.has_sideeffects(spaceop): return 'green' colors = {} for graph, tsgraph in self.graphs_from(spaceop): From pedronis at codespeak.net Thu Dec 28 14:59:56 2006 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Thu, 28 Dec 2006 14:59:56 +0100 (CET) Subject: [pypy-svn] r36022 - in pypy/dist/pypy/jit/timeshifter: . test Message-ID: <20061228135956.C0CD710072@code0.codespeak.net> Author: pedronis Date: Thu Dec 28 14:59:51 2006 New Revision: 36022 Modified: pypy/dist/pypy/jit/timeshifter/hrtyper.py pypy/dist/pypy/jit/timeshifter/test/test_timeshift.py Log: fix erasure of Char for merge point keys. with test. Modified: pypy/dist/pypy/jit/timeshifter/hrtyper.py ============================================================================== --- pypy/dist/pypy/jit/timeshifter/hrtyper.py (original) +++ pypy/dist/pypy/jit/timeshifter/hrtyper.py Thu Dec 28 14:59:51 2006 @@ -1084,8 +1084,13 @@ s_erased_type = r.erased_annotation() r_precise_type = self.rtyper.getrepr(s_precise_type) r_erased_type = self.rtyper.getrepr(s_erased_type) - greens_v.append(hop.llops.convertvar(v, r_precise_type, - r_erased_type)) + if r_precise_type.lowleveltype == lltype.Char: + v_green = hop.llops.genop('cast_char_to_int', [v], + resulttype = lltype.Signed) + else: + v_green = hop.llops.convertvar(v, r_precise_type, r_erased_type) + + greens_v.append(v_green) greens_s.append(s_erased_type) v_jitstate = hop.llops.getjitstate() 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 Dec 28 14:59:51 2006 @@ -375,7 +375,7 @@ def test_loop_folding(self): def ll_function(x, y): tot = 0 - x = hint(x, concrete=True) + x = hint(x, concrete=True) while x: tot += y x -= 1 @@ -1210,3 +1210,20 @@ res = self.timeshift(f, [4, 212], [], policy=P_NOVIRTUAL) assert res == 212 + + def test_green_char_at_merge(self): + def f(c, x): + c = chr(c) + c = hint(c, concrete=True) + if x: + x = 3 + else: + x = 1 + c = hint(c, variable=True) + return len(c*x) + + res = self.timeshift(f, [ord('a'), 1], [], policy=P_NOVIRTUAL) + assert res == 3 + + res = self.timeshift(f, [ord('b'), 0], [], policy=P_NOVIRTUAL) + assert res == 1 From arigo at codespeak.net Thu Dec 28 17:59:48 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 28 Dec 2006 17:59:48 +0100 (CET) Subject: [pypy-svn] r36024 - in pypy/dist/pypy/rlib/rctypes: . test Message-ID: <20061228165948.5F9C910082@code0.codespeak.net> Author: arigo Date: Thu Dec 28 17:59:44 2006 New Revision: 36024 Added: pypy/dist/pypy/rlib/rctypes/rbuiltin.py (contents, props changed) Modified: pypy/dist/pypy/rlib/rctypes/implementation.py pypy/dist/pypy/rlib/rctypes/rctypesobject.py pypy/dist/pypy/rlib/rctypes/rpointer.py pypy/dist/pypy/rlib/rctypes/rprimitive.py pypy/dist/pypy/rlib/rctypes/test/test_rprimitive.py Log: Implement sizeof(). All remaining rprimitive tests pass. Modified: pypy/dist/pypy/rlib/rctypes/implementation.py ============================================================================== --- pypy/dist/pypy/rlib/rctypes/implementation.py (original) +++ pypy/dist/pypy/rlib/rctypes/implementation.py Thu Dec 28 17:59:44 2006 @@ -122,17 +122,24 @@ return hop2 def register_function_impl(builtinfn, controllingfn, - revealargs=[], revealresult=None): + revealargs=[], revealresult=None, + register=True): class Entry(extregistry.ExtRegistryEntry): - _about_ = builtinfn + if register: + _about_ = builtinfn def compute_result_annotation(self, *args_s): real_args_s = list(args_s) - for index in revealargs: - real_args_s[index] = args_s[index].s_real_obj if annmodel.s_ImpossibleValue in real_args_s: return annmodel.s_ImpossibleValue # temporarily hopefully + for index in revealargs: + s_controlled = args_s[index] + if not isinstance(s_controlled, SomeControlledInstance): + raise TypeError("in call to %s:\nargs_s[%d] should be a " + "ControlledInstance,\ngot instead %s" % ( + builtinfn, index, s_controlled)) + real_args_s[index] = s_controlled.s_real_obj s_result = controllerentry.delegate(controllingfn, *real_args_s) if revealresult: result_ctype = revealresult(*args_s) @@ -145,6 +152,8 @@ from pypy.rpython.rcontrollerentry import rtypedelegate return rtypedelegate(controllingfn, hop, revealargs, revealresult) + return Entry + # ____________________________________________________________ # # Imports for side-effects @@ -153,3 +162,4 @@ import pypy.rlib.rctypes.rarray import pypy.rlib.rctypes.rpointer import pypy.rlib.rctypes.rstruct +import pypy.rlib.rctypes.rbuiltin Added: pypy/dist/pypy/rlib/rctypes/rbuiltin.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/rlib/rctypes/rbuiltin.py Thu Dec 28 17:59:44 2006 @@ -0,0 +1,46 @@ +from pypy.annotation import model as annmodel +from pypy.rpython.lltypesystem import lltype +from pypy.rpython.error import TyperError +from pypy.rpython.controllerentry import SomeControlledInstance +from pypy.rlib.rctypes.implementation import getcontroller +from pypy.rlib.rctypes.implementation import register_function_impl +from pypy.rlib.rctypes import rctypesobject + +import ctypes + +# +# pointer() +# +register_function_impl(ctypes.pointer, rctypesobject.pointer, + revealargs = [0], + revealresult = lambda s_obj: ctypes.POINTER( + s_obj.controller.ctype)) + +# +# sizeof() +# +sizeof_base_entry = register_function_impl(ctypes.sizeof, rctypesobject.sizeof, + revealargs=[0], register=False) + +class Entry(sizeof_base_entry): + _about_ = ctypes.sizeof + + def compute_result_annotation(self, s_arg): + return annmodel.SomeInteger(nonneg=True) + + def specialize_call(self, hop): + s_arg = hop.args_s[0] + if isinstance(s_arg, SomeControlledInstance): + # sizeof(object) + return sizeof_base_entry.specialize_call(self, hop) + else: + # sizeof(type) + if not s_arg.is_constant(): + raise TyperError("only supports sizeof(object) or " + "sizeof(constant-type)") + ctype = s_arg.const + sample = ctype() # XXX can we always instantiate ctype like this? + controller = getcontroller(ctype) + real_obj = controller.convert(sample) + size = rctypesobject.sizeof(real_obj) + return hop.inputconst(lltype.Signed, size) Modified: pypy/dist/pypy/rlib/rctypes/rctypesobject.py ============================================================================== --- pypy/dist/pypy/rlib/rctypes/rctypesobject.py (original) +++ pypy/dist/pypy/rlib/rctypes/rctypesobject.py Thu Dec 28 17:59:44 2006 @@ -99,6 +99,9 @@ def sameaddr(self, otherbox): return self.addr == otherbox.addr + def sizeof(self): + return self.rawsize + def _keepalivememblock(self, index, memblock): self.memblock.setkeepalive(index, memblock) @@ -266,6 +269,9 @@ return p pointer._annspecialcase_ = 'specialize:argtype(0)' +def sizeof(x): + return x.sizeof() + # ____________________________________________________________ def RStruct(c_name, fields, c_external=False): @@ -375,6 +381,10 @@ self.memblock = memblock self.length = length + def sizeof(self): + rawsize = FIRSTITEMOFS + ITEMOFS * self.length + return rawsize + def allocate(length): rawsize = FIRSTITEMOFS + ITEMOFS * length num_keepalives = itemcls.num_keepalives * length Modified: pypy/dist/pypy/rlib/rctypes/rpointer.py ============================================================================== --- pypy/dist/pypy/rlib/rctypes/rpointer.py (original) +++ pypy/dist/pypy/rlib/rctypes/rpointer.py Thu Dec 28 17:59:44 2006 @@ -1,6 +1,5 @@ from pypy.rpython.extregistry import ExtRegistryEntry from pypy.rlib.rctypes.implementation import CTypeController, getcontroller -from pypy.rlib.rctypes.implementation import register_function_impl from pypy.rlib.rctypes import rctypesobject from pypy.rpython.lltypesystem import lltype @@ -39,8 +38,3 @@ setitem._annspecialcase_ = 'specialize:arg(0)' PointerCTypeController.register_for_metatype(PointerType) - -register_function_impl(pointer, rctypesobject.pointer, - revealargs = [0], - revealresult = lambda s_obj: POINTER(s_obj.controller - .ctype)) Modified: pypy/dist/pypy/rlib/rctypes/rprimitive.py ============================================================================== --- pypy/dist/pypy/rlib/rctypes/rprimitive.py (original) +++ pypy/dist/pypy/rlib/rctypes/rprimitive.py Thu Dec 28 17:59:44 2006 @@ -50,7 +50,14 @@ new._annspecialcase_ = 'specialize:arg(0)' def initialize_prebuilt(self, obj, x): - self.set_value(obj, x.value) + value = x.value + # convert 'value' to anything that cast_primitive will be happy with + if type(value) is long: + if value >= 0: + value = rcarith.rculonglong(value) + else: + value = rcarith.rclonglong(value) + self.set_value(obj, value) def get_value(self, obj): llvalue = obj.get_value() Modified: pypy/dist/pypy/rlib/rctypes/test/test_rprimitive.py ============================================================================== --- pypy/dist/pypy/rlib/rctypes/test/test_rprimitive.py (original) +++ pypy/dist/pypy/rlib/rctypes/test/test_rprimitive.py Thu Dec 28 17:59:44 2006 @@ -379,7 +379,7 @@ assert res == 19 -class INPROGRESS_Test_compilation: +class Test_compilation: def setup_class(self): if not test_c_compile: py.test.skip("c compilation disabled") @@ -527,7 +527,7 @@ fn = self.compile(func, [int]) assert fn(19) == func(19) -class INPROGRESS_Test_compilation_llvm(INPROGRESS_Test_compilation): +class Test_compilation_llvm(Test_compilation): def setup_class(self): if not test_llvm_compile: py.test.skip("llvm compilation disabled") From arigo at codespeak.net Thu Dec 28 18:07:05 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 28 Dec 2006 18:07:05 +0100 (CET) Subject: [pypy-svn] r36025 - in pypy/dist/pypy/objspace/fake: . test Message-ID: <20061228170705.D31FC10082@code0.codespeak.net> Author: arigo Date: Thu Dec 28 18:07:03 2006 New Revision: 36025 Modified: pypy/dist/pypy/objspace/fake/ (props changed) pypy/dist/pypy/objspace/fake/test/ (props changed) Log: fixeol From arigo at codespeak.net Thu Dec 28 18:08:51 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 28 Dec 2006 18:08:51 +0100 (CET) Subject: [pypy-svn] r36026 - pypy/dist/pypy/rpython/test Message-ID: <20061228170851.9FEFD1008F@code0.codespeak.net> Author: arigo Date: Thu Dec 28 18:08:50 2006 New Revision: 36026 Modified: pypy/dist/pypy/rpython/test/test_llinterp.py pypy/dist/pypy/rpython/test/test_rbuiltin.py pypy/dist/pypy/rpython/test/test_robject.py Log: Change all interpret() tests to annotate with SomeObject disabled by default. The flag 'someobjects=True' can be used to override this. Modified: pypy/dist/pypy/rpython/test/test_llinterp.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_llinterp.py (original) +++ pypy/dist/pypy/rpython/test/test_llinterp.py Thu Dec 28 18:08:50 2006 @@ -76,6 +76,11 @@ else: return lltype_to_annotation(T) + if policy is None and not someobjects: + from pypy.annotation.policy import AnnotatorPolicy + policy = AnnotatorPolicy() + policy.allow_someobjects = False + t, typer, graph = gengraph(func, [annotation(x) for x in values], viewbefore, policy, type_system=type_system, backendopt=backendopt, config=config) @@ -242,7 +247,7 @@ def test_unicode(): def f(): return u'Hello world' - res = interpret(f,[]) + res = interpret(f, [], someobjects=True) assert res._obj.value == u'Hello world' 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 Thu Dec 28 18:08:50 2006 @@ -359,7 +359,7 @@ if i==1: return int(hasattr(A, 'y')) if i==2: return int(hasattr(42, 'x')) for x, y in zip(range(3), (1, 0, 0)): - res = self.interpret(f, [x]) + res = self.interpret(f, [x], someobjects=True) assert res._obj.value == y # hmm, would like to test against PyObj, is this the wrong place/way? Modified: pypy/dist/pypy/rpython/test/test_robject.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_robject.py (original) +++ pypy/dist/pypy/rpython/test/test_robject.py Thu Dec 28 18:08:50 2006 @@ -17,9 +17,9 @@ d['ab'] = c d[i] = c return len(d) - res = interpret(f, [2, 'c']) + res = interpret(f, [2, 'c'], someobjects=True) assert res == 4 - res = interpret(f, [3, 'c']) + res = interpret(f, [3, 'c'], someobjects=True) assert res == 4 def test_obj_list(): @@ -28,9 +28,9 @@ lis[i] = c lis.append(i) return len(lis) - res = interpret(f, [2, 'c']) + res = interpret(f, [2, 'c'], someobjects=True) assert res == 5 - res = interpret(f, [3, 'c']) + res = interpret(f, [3, 'c'], someobjects=True) assert res == 5 def test_obj_iter(): @@ -41,9 +41,9 @@ x = '34' lst = [u for u in x] return lst[flag] - res = interpret(f, [1]) + res = interpret(f, [1], someobjects=True) assert res._obj.value == 2 - res = interpret(f, [0]) + res = interpret(f, [0], someobjects=True) assert res._obj.value == '3' def test_listofobj_iter(): @@ -53,7 +53,7 @@ if u == look: return True return False - res = interpret(f, [1]) + res = interpret(f, [1], someobjects=True) assert res is False - res = interpret(f, [2]) + res = interpret(f, [2], someobjects=True) assert res is True From arigo at codespeak.net Thu Dec 28 19:02:56 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 28 Dec 2006 19:02:56 +0100 (CET) Subject: [pypy-svn] r36027 - in pypy/dist/pypy: rlib/rctypes rlib/rctypes/test rpython Message-ID: <20061228180256.8AEA010092@code0.codespeak.net> Author: arigo Date: Thu Dec 28 19:02:53 2006 New Revision: 36027 Added: pypy/dist/pypy/rlib/rctypes/test/test_rpointer.py - copied, changed from r36026, pypy/dist/pypy/rpython/rctypes/test/test_rpointer.py Modified: pypy/dist/pypy/rlib/rctypes/implementation.py pypy/dist/pypy/rlib/rctypes/rbuiltin.py pypy/dist/pypy/rlib/rctypes/rpointer.py pypy/dist/pypy/rlib/rctypes/test/test_rprimitive.py pypy/dist/pypy/rpython/controllerentry.py Log: Annotate ctypes.pointer tests. Some hacking in controllerentry to add an explicit way to "convert" between SomeControlledInstance and its underlying, revealed object. Modified: pypy/dist/pypy/rlib/rctypes/implementation.py ============================================================================== --- pypy/dist/pypy/rlib/rctypes/implementation.py (original) +++ pypy/dist/pypy/rlib/rctypes/implementation.py Thu Dec 28 19:02:53 2006 @@ -1,3 +1,4 @@ +import py from pypy.annotation import model as annmodel from pypy.rlib.rctypes import rctypesobject from pypy.rpython import extregistry, controllerentry @@ -8,10 +9,13 @@ from pypy.rpython.lltypesystem import lltype from pypy.rpython.rctypes import rcarithmetic as rcarith -import ctypes -if ctypes.__version__ < '0.9.9.6': # string comparison... good enough? - raise ImportError("requires ctypes >= 0.9.9.6, got %s" % ( - ctypes.__version__,)) +try: + import ctypes + if ctypes.__version__ < '0.9.9.6': # string comparison... good enough? + raise ImportError("requires ctypes >= 0.9.9.6, got %s" % ( + ctypes.__version__,)) +except ImportError, e: + py.test.skip(str(e)) class CTypeController(Controller): @@ -49,9 +53,7 @@ self.initialize_prebuilt(obj, x) return obj - def return_value(self, obj): - return obj - return_value._annspecialcase_ = 'specialize:arg(0)' + return_value = Controller.box # extension to the setattr/setitem support: if the new value is actually # a CTypeControlled instance as well, reveal it automatically (i.e. turn Modified: pypy/dist/pypy/rlib/rctypes/rbuiltin.py ============================================================================== --- pypy/dist/pypy/rlib/rctypes/rbuiltin.py (original) +++ pypy/dist/pypy/rlib/rctypes/rbuiltin.py Thu Dec 28 19:02:53 2006 @@ -1,6 +1,7 @@ from pypy.annotation import model as annmodel from pypy.rpython.lltypesystem import lltype from pypy.rpython.error import TyperError +from pypy.rpython.extregistry import ExtRegistryEntry from pypy.rpython.controllerentry import SomeControlledInstance from pypy.rlib.rctypes.implementation import getcontroller from pypy.rlib.rctypes.implementation import register_function_impl @@ -17,6 +18,32 @@ s_obj.controller.ctype)) # +# POINTER() +# +class Entry(ExtRegistryEntry): + "Annotation and rtyping of calls to ctypes.POINTER(): constant-folded." + _about_ = ctypes.POINTER + + def compute_result_annotation(self, s_arg): + # POINTER(constant_ctype) returns the constant annotation + # corresponding to the POINTER(ctype). + assert s_arg.is_constant(), ( + "POINTER(%r): argument must be constant" % (s_arg,)) + RESTYPE = ctypes.POINTER(s_arg.const) + # POINTER(varsized_array_type): given that rctypes performs + # no index checking, this pointer-to-array type is equivalent + # to a pointer to an array of whatever size. + # ('0' is a bad idea, though, as FixedSizeArrays of length 0 + # tend to say they have impossible items.) + #XXX: RESTYPE = POINTER(s_arg.ctype_array._type_ * 1) + return self.bookkeeper.immutablevalue(RESTYPE) + + def specialize_call(self, hop): + assert hop.s_result.is_constant() + hop.exception_cannot_occur() + return hop.inputconst(lltype.Void, hop.s_result.const) + +# # sizeof() # sizeof_base_entry = register_function_impl(ctypes.sizeof, rctypesobject.sizeof, @@ -43,4 +70,5 @@ controller = getcontroller(ctype) real_obj = controller.convert(sample) size = rctypesobject.sizeof(real_obj) + hop.exception_cannot_occur() return hop.inputconst(lltype.Signed, size) Modified: pypy/dist/pypy/rlib/rctypes/rpointer.py ============================================================================== --- pypy/dist/pypy/rlib/rctypes/rpointer.py (original) +++ pypy/dist/pypy/rlib/rctypes/rpointer.py Thu Dec 28 19:02:53 2006 @@ -17,11 +17,16 @@ self.knowntype = rctypesobject.RPointer( self.contentscontroller.knowntype) - def new(self): + def new(self, ptrto=None): obj = self.knowntype.allocate() - #... + if ptrto is not None: + obj.set_contents(self.contentscontroller.unbox(ptrto)) return obj + def initialize_prebuilt(self, obj, x): + contentsbox = self.contentscontroller.convert(x.contents) + self.setbox_contents(obj, contentsbox) + def getitem(self, obj, index): if index != 0: raise ValueError("can only access item 0 of pointers") @@ -37,4 +42,20 @@ self.contentscontroller.set_value(contentsobj, value) setitem._annspecialcase_ = 'specialize:arg(0)' + def setboxitem(self, obj, index, valuebox): + if index != 0: + raise ValueError("assignment to pointer[x] with x != 0") + # not supported by ctypes either + contentsobj = obj.get_contents() + contentsobj.copyfrom(valuebox) + setitem._annspecialcase_ = 'specialize:arg(0)' + + def get_contents(self, obj): + return self.contentscontroller.box(obj.get_contents()) + get_contents._annspecialcase_ = 'specialize:arg(0)' + + def setbox_contents(self, obj, contentsbox): + obj.set_contents(contentsbox) + setbox_contents._annspecialcase_ = 'specialize:arg(0)' + PointerCTypeController.register_for_metatype(PointerType) Modified: pypy/dist/pypy/rlib/rctypes/test/test_rprimitive.py ============================================================================== --- pypy/dist/pypy/rlib/rctypes/test/test_rprimitive.py (original) +++ pypy/dist/pypy/rlib/rctypes/test/test_rprimitive.py Thu Dec 28 19:02:53 2006 @@ -6,12 +6,12 @@ import pypy.rlib.rctypes.implementation from pypy.annotation.annrpython import RPythonAnnotator from pypy.annotation import policy -from pypy.annotation.model import SomeCTypesObject, SomeObject from pypy import conftest import sys from pypy.rpython.test.test_llinterp import interpret from pypy.rlib.rarithmetic import r_longlong, r_ulonglong from pypy.rpython.lltypesystem import lltype + from ctypes import c_char, c_byte, c_ubyte, c_short, c_ushort, c_int, c_uint from ctypes import c_long, c_ulong, c_longlong, c_ulonglong, c_float from ctypes import c_double, c_wchar, c_char_p, pointer, sizeof @@ -20,7 +20,7 @@ test_c_compile = True test_llvm_compile = False -class Test_annotation: +class BaseTestAnnotation: def build_types(self, func, argtypes): P = policy.AnnotatorPolicy() P.allow_someobjects = False @@ -30,6 +30,7 @@ a.translator.view() return s +class Test_annotation(BaseTestAnnotation): def test_simple(self): res = c_int(42) assert res.value == 42 Modified: pypy/dist/pypy/rpython/controllerentry.py ============================================================================== --- pypy/dist/pypy/rpython/controllerentry.py (original) +++ pypy/dist/pypy/rpython/controllerentry.py Thu Dec 28 19:02:53 2006 @@ -42,6 +42,14 @@ def _freeze_(self): return True + def box(self, obj): + return controlled_instance_box(self, obj) + box._annspecialcase_ = 'specialize:arg(0)' + + def unbox(self, obj): + return controlled_instance_unbox(self, obj) + unbox._annspecialcase_ = 'specialize:arg(0)' + def ctrl_new(self, *args_s): s_real_obj = delegate(self.new, *args_s) if s_real_obj == annmodel.s_ImpossibleValue: @@ -103,6 +111,41 @@ return bk.emulate_pbc_call(bk.position_key, s_meth, args_s, callback = bk.position_key) +def controlled_instance_box(controller, obj): + XXX + +def controlled_instance_unbox(controller, obj): + XXX + +class BoxEntry(ExtRegistryEntry): + _about_ = controlled_instance_box + + def compute_result_annotation(self, s_controller, s_real_obj): + if s_real_obj == annmodel.s_ImpossibleValue: + return annmodel.s_ImpossibleValue + else: + assert s_controller.is_constant() + controller = s_controller.const + return SomeControlledInstance(s_real_obj, controller=controller) + + def specialize_call(self, hop): + [v] = hop.inputargs(hop.r_result) + return v + +class UnboxEntry(ExtRegistryEntry): + _about_ = controlled_instance_unbox + + def compute_result_annotation(self, s_controller, s_obj): + if s_obj == annmodel.s_ImpossibleValue: + return annmodel.s_ImpossibleValue + else: + assert isinstance(s_obj, SomeControlledInstance) + return s_obj.s_real_obj + + def specialize_call(self, hop): + [v] = hop.inputargs(hop.r_result) + return v + # ____________________________________________________________ class SomeControlledInstance(annmodel.SomeObject): From cfbolz at codespeak.net Thu Dec 28 19:24:33 2006 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Thu, 28 Dec 2006 19:24:33 +0100 (CET) Subject: [pypy-svn] r36028 - pypy/dist/pypy/module/bz2 Message-ID: <20061228182433.030AA10092@code0.codespeak.net> Author: cfbolz Date: Thu Dec 28 19:24:21 2006 New Revision: 36028 Modified: pypy/dist/pypy/module/bz2/interp_bz2.py Log: bz2 compiles with these small changes. Especially obvious is the removal of the NOT_RPYTHON line :-) 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 Thu Dec 28 19:24:21 2006 @@ -228,6 +228,8 @@ def read(self, n): # XXX not nice + if n <= 0: + return '' while not self.buffer: if self.finished: return "" @@ -237,6 +239,7 @@ if e.match(self.space, self.space.w_EOFError): self.finished = True return "" + raise self.buffer = self.space.str_w(w_read) if len(self.buffer) >= n: result = self.buffer[:n] @@ -259,8 +262,6 @@ """Standard I/O stream filter that compresses the stream with bz2.""" def __init__(self, space, stream, compresslevel): - """NOT_RPYTHON""" - import bz2 self.stream = stream self.space = space self.compressor = W_BZ2Compressor(space, compresslevel) From antocuni at codespeak.net Fri Dec 29 11:22:39 2006 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Fri, 29 Dec 2006 11:22:39 +0100 (CET) Subject: [pypy-svn] r36031 - in pypy/dist/pypy/translator: . goal Message-ID: <20061229102239.143A71009B@code0.codespeak.net> Author: antocuni Date: Fri Dec 29 11:22:33 2006 New Revision: 36031 Modified: pypy/dist/pypy/translator/driver.py pypy/dist/pypy/translator/goal/bench-cronjob.py Log: Rename also the directory containing the actual pypy.net, not only the wrapper script. Modified: pypy/dist/pypy/translator/driver.py ============================================================================== --- pypy/dist/pypy/translator/driver.py (original) +++ pypy/dist/pypy/translator/driver.py Fri Dec 29 11:22:33 2006 @@ -610,8 +610,8 @@ newexename = basename f = file(newexename, 'w') f.write("""#!/bin/bash -mono "$(dirname $0)/%s/%s" "$@" # XXX doesn't work if it's placed in PATH -""" % (dirname, main_exe_name)) +mono "$(dirname $0)/$(basename $0)-data/%s" "$@" # XXX doesn't work if it's placed in PATH +""" % main_exe_name) f.close() os.chmod(newexename, 0755) Modified: pypy/dist/pypy/translator/goal/bench-cronjob.py ============================================================================== --- pypy/dist/pypy/translator/goal/bench-cronjob.py (original) +++ pypy/dist/pypy/translator/goal/bench-cronjob.py Fri Dec 29 11:22:33 2006 @@ -133,6 +133,10 @@ compile_llvm_variants(revision, features) elif os.path.exists(basename): #copy executable run("mv %s %s" % (basename, realname)) + if backend == 'cli': + basename_dir = basename + '-data' + realname_dir = realname + '-data' + run("mv %s %s" % (basename_dir, realname_dir)) #pypy = open(basename, 'rb').read() #if len(pypy) > 0: # open(realname, 'wb').write(pypy) From arigo at codespeak.net Fri Dec 29 13:22:16 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 29 Dec 2006 13:22:16 +0100 (CET) Subject: [pypy-svn] r36034 - pypy/dist/pypy/module/bz2 Message-ID: <20061229122216.32A8710088@code0.codespeak.net> Author: arigo Date: Fri Dec 29 13:22:15 2006 New Revision: 36034 Modified: pypy/dist/pypy/module/bz2/interp_bz2.py Log: Remove tabs. 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 Fri Dec 29 13:22:15 2006 @@ -239,7 +239,7 @@ if e.match(self.space, self.space.w_EOFError): self.finished = True return "" - raise + raise self.buffer = self.space.str_w(w_read) if len(self.buffer) >= n: result = self.buffer[:n] From antocuni at codespeak.net Fri Dec 29 14:34:43 2006 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Fri, 29 Dec 2006 14:34:43 +0100 (CET) Subject: [pypy-svn] r36035 - in pypy/dist/pypy/translator/backendopt: . test Message-ID: <20061229133443.89BB110088@code0.codespeak.net> Author: antocuni Date: Fri Dec 29 14:34:40 2006 New Revision: 36035 Modified: pypy/dist/pypy/translator/backendopt/malloc.py pypy/dist/pypy/translator/backendopt/test/test_malloc.py Log: First steps in making malloc removal ootype-compatible. Modified: pypy/dist/pypy/translator/backendopt/malloc.py ============================================================================== --- pypy/dist/pypy/translator/backendopt/malloc.py (original) +++ pypy/dist/pypy/translator/backendopt/malloc.py Fri Dec 29 14:34:40 2006 @@ -18,138 +18,246 @@ self.creationpoints.update(other.creationpoints) self.usepoints.update(other.usepoints) +class BaseMallocRemover(object): -def equivalent_substruct(S, fieldname): - # we consider a pointer to a GcStruct S as equivalent to a - # pointer to a substructure 'S.fieldname' if it's the first - # inlined sub-GcStruct. As an extension we also allow a pointer - # to a GcStruct containing just one field to be equivalent to - # a pointer to that field only (although a mere cast_pointer - # would not allow casting). This is needed to malloc-remove - # the 'wrapper' GcStructs introduced by previous passes of - # malloc removal. - if not isinstance(S, lltype.GcStruct): - return False - if fieldname != S._names[0]: + IDENTITY_OPS = ('same_as',) + SUBSTRUCT_OPS = () + MALLOC_OP = None + FIELD_ACCESS = {} + SUBSTRUCT_ACCESS = {} + CHECK_ARRAY_INDEX = {} + + def get_STRUCT(self, TYPE): + raise NotImplementedError + + def do_substruct_access(self, op): + raise NotImplementedError + + def equivalent_substruct(self, S, fieldname): + raise NotImplementedError + + def union_wrapper(self, S): return False - FIELDTYPE = S._flds[fieldname] - if isinstance(FIELDTYPE, lltype.GcStruct): - if FIELDTYPE._hints.get('union'): - return False - return True - if len(S._names) == 1: - return True - return False - -def union_wrapper(S): - # check if 'S' is a GcStruct containing a single inlined *union* Struct - if not isinstance(S, lltype.GcStruct): + + def RTTI_dtor(self, STRUCT): return False - assert not S._hints.get('union') # not supported: "GcUnion" - return (len(S._names) == 1 and - isinstance(S._flds[S._names[0]], lltype.Struct) and - S._flds[S._names[0]]._hints.get('union')) - - -def compute_lifetimes(graph): - """Compute the static data flow of the graph: returns a list of LifeTime - instances, each of which corresponds to a set of Variables from the graph. - The variables are grouped in the same LifeTime if a value can pass from - one to the other by following the links. Each LifeTime also records all - places where a Variable in the set is used (read) or build (created). - """ - lifetimes = UnionFind(LifeTime) - - def set_creation_point(block, var, *cp): - _, _, info = lifetimes.find((block, var)) - info.creationpoints[cp] = True - - def set_use_point(block, var, *up): - _, _, info = lifetimes.find((block, var)) - info.usepoints[up] = True - - def union(block1, var1, block2, var2): - if isinstance(var1, Variable): - lifetimes.union((block1, var1), (block2, var2)) - elif isinstance(var1, Constant): - set_creation_point(block2, var2, "constant", var1) - else: - raise TypeError(var1) - - for var in graph.startblock.inputargs: - set_creation_point(graph.startblock, var, "inputargs") - set_use_point(graph.returnblock, graph.returnblock.inputargs[0], "return") - set_use_point(graph.exceptblock, graph.exceptblock.inputargs[0], "except") - set_use_point(graph.exceptblock, graph.exceptblock.inputargs[1], "except") - - def visit(node): - if isinstance(node, Block): - for op in node.operations: - if op.opname in ("same_as", "cast_pointer"): - # special-case these operations to identify their input - # and output variables - union(node, op.args[0], node, op.result) - continue - if op.opname in ('getsubstruct', 'direct_fieldptr'): - S = op.args[0].concretetype.TO - if equivalent_substruct(S, op.args[1].value): - # assumed to be similar to a cast_pointer + + def flatten(self, S): + raise NotImplementedError + + def key_for_field_access(self, S, fldname): + raise NotImplementedError + + def flowin(self, block, count, var, newvarsmap): + raise NotImplementedError + + def compute_lifetimes(self, graph): + """Compute the static data flow of the graph: returns a list of LifeTime + instances, each of which corresponds to a set of Variables from the graph. + The variables are grouped in the same LifeTime if a value can pass from + one to the other by following the links. Each LifeTime also records all + places where a Variable in the set is used (read) or build (created). + """ + lifetimes = UnionFind(LifeTime) + + def set_creation_point(block, var, *cp): + _, _, info = lifetimes.find((block, var)) + info.creationpoints[cp] = True + + def set_use_point(block, var, *up): + _, _, info = lifetimes.find((block, var)) + info.usepoints[up] = True + + def union(block1, var1, block2, var2): + if isinstance(var1, Variable): + lifetimes.union((block1, var1), (block2, var2)) + elif isinstance(var1, Constant): + set_creation_point(block2, var2, "constant", var1) + else: + raise TypeError(var1) + + for var in graph.startblock.inputargs: + set_creation_point(graph.startblock, var, "inputargs") + set_use_point(graph.returnblock, graph.returnblock.inputargs[0], "return") + set_use_point(graph.exceptblock, graph.exceptblock.inputargs[0], "except") + set_use_point(graph.exceptblock, graph.exceptblock.inputargs[1], "except") + + def visit(node): + if isinstance(node, Block): + for op in node.operations: + if op.opname in self.IDENTITY_OPS: + # special-case these operations to identify their input + # and output variables union(node, op.args[0], node, op.result) continue - for i in range(len(op.args)): - if isinstance(op.args[i], Variable): - set_use_point(node, op.args[i], "op", node, op, i) - set_creation_point(node, op.result, "op", node, op) - if isinstance(node.exitswitch, Variable): - set_use_point(node, node.exitswitch, "exitswitch", node) - - if isinstance(node, Link): - if isinstance(node.last_exception, Variable): - set_creation_point(node.prevblock, node.last_exception, - "last_exception") - if isinstance(node.last_exc_value, Variable): - set_creation_point(node.prevblock, node.last_exc_value, - "last_exc_value") - d = {} - for i, arg in enumerate(node.args): - union(node.prevblock, arg, - node.target, node.target.inputargs[i]) - if isinstance(arg, Variable): - if arg in d: - # same variable present several times in link.args - # consider it as a 'use' of the variable, which - # will disable malloc optimization (aliasing problems) - set_use_point(node.prevblock, arg, "dup", node, i) - else: - d[arg] = True + if op.opname in self.SUBSTRUCT_OPS: + S = op.args[0].concretetype.TO + if self.equivalent_substruct(S, op.args[1].value): + # assumed to be similar to a cast_pointer + union(node, op.args[0], node, op.result) + continue + for i in range(len(op.args)): + if isinstance(op.args[i], Variable): + set_use_point(node, op.args[i], "op", node, op, i) + set_creation_point(node, op.result, "op", node, op) + if isinstance(node.exitswitch, Variable): + set_use_point(node, node.exitswitch, "exitswitch", node) + + if isinstance(node, Link): + if isinstance(node.last_exception, Variable): + set_creation_point(node.prevblock, node.last_exception, + "last_exception") + if isinstance(node.last_exc_value, Variable): + set_creation_point(node.prevblock, node.last_exc_value, + "last_exc_value") + d = {} + for i, arg in enumerate(node.args): + union(node.prevblock, arg, + node.target, node.target.inputargs[i]) + if isinstance(arg, Variable): + if arg in d: + # same variable present several times in link.args + # consider it as a 'use' of the variable, which + # will disable malloc optimization (aliasing problems) + set_use_point(node.prevblock, arg, "dup", node, i) + else: + d[arg] = True - traverse(visit, graph) - return lifetimes.infos() + traverse(visit, graph) + return lifetimes.infos() -def _try_inline_malloc(info): - """Try to inline the mallocs creation and manipulation of the Variables - in the given LifeTime.""" - # the values must be only ever created by a "malloc" - lltypes = {} - for cp in info.creationpoints: - if cp[0] != "op": + def _try_inline_malloc(self, info): + """Try to inline the mallocs creation and manipulation of the Variables + in the given LifeTime.""" + # the values must be only ever created by a "malloc" + lltypes = {} + for cp in info.creationpoints: + if cp[0] != "op": + return False + op = cp[2] + if op.opname != self.MALLOC_OP: + return False + lltypes[op.result.concretetype] = True + + # there must be a single largest malloced GcStruct; + # all variables can point to it or to initial substructures + if len(lltypes) != 1: return False - op = cp[2] - if op.opname != "malloc": + STRUCT = self.get_STRUCT(lltypes.keys()[0]) + + # must be only ever accessed via getfield/setfield/getsubstruct/ + # direct_fieldptr, or touched by keepalive or ptr_iszero/ptr_nonzero. + # Note that same_as and cast_pointer are not recorded in usepoints. + self.accessed_substructs = {} + + for up in info.usepoints: + if up[0] != "op": + return False + kind, node, op, index = up + if index != 0: + return False + if op.opname in self.CHECK_ARRAY_INDEX: + if not isinstance(op.args[1], Constant): + return False # non-constant array index + if op.opname in self.FIELD_ACCESS: + pass # ok + elif op.opname in self.SUBSTRUCT_ACCESS: + self.do_substruct_access(op) + else: + return False + + # must not remove mallocs of structures that have a RTTI with a destructor + if self.RTTI_dtor(STRUCT): return False - lltypes[op.result.concretetype] = True - # there must be a single largest malloced GcStruct; - # all variables can point to it or to initial substructures - if len(lltypes) != 1: - return False - STRUCT = lltypes.keys()[0].TO - assert isinstance(STRUCT, lltype.GcStruct) + # must not remove unions inlined as the only field of a GcStruct + if self.union_wrapper(STRUCT): + return False + + # success: replace each variable with a family of variables (one per field) + + # 'flatnames' is a list of (STRUCTTYPE, fieldname_in_that_struct) that + # describes the list of variables that should replace the single + # malloc'ed pointer variable that we are about to remove. For primitive + # or pointer fields, the new corresponding variable just stores the + # actual value. For substructures, if pointers to them are "equivalent" + # to pointers to the parent structure (see equivalent_substruct()) then + # they are just merged, and flatnames will also list the fields within + # that substructure. Other substructures are replaced by a single new + # variable which is a pointer to a GcStruct-wrapper; each is malloc'ed + # individually, in an exploded way. (The next malloc removal pass will + # get rid of them again, in the typical case.) + self.flatnames = [] + self.flatconstants = {} + self.needsubmallocs = [] + self.newvarstype = {} # map {item-of-flatnames: concretetype} + self.direct_fieldptr_key = {} + self.flatten(STRUCT) + assert len(self.direct_fieldptr_key) <= 1 + + variables_by_block = {} + for block, var in info.variables: + vars = variables_by_block.setdefault(block, {}) + vars[var] = True + + count = [0] + + for block, vars in variables_by_block.items(): + + # look for variables arriving from outside the block + for var in vars: + if var in block.inputargs: + i = block.inputargs.index(var) + newinputargs = block.inputargs[:i] + newvarsmap = {} + for key in self.flatnames: + newvar = Variable() + newvar.concretetype = self.newvarstype[key] + newvarsmap[key] = newvar + newinputargs.append(newvar) + newinputargs += block.inputargs[i+1:] + block.inputargs[:] = newinputargs + assert var not in block.inputargs + self.flowin(block, count, var, newvarsmap) + + # look for variables created inside the block by a malloc + vars_created_here = [] + for op in block.operations: + if op.opname == self.MALLOC_OP and op.result in vars: + vars_created_here.append(op.result) + for var in vars_created_here: + self.flowin(block, count, var, newvarsmap=None) + + return count[0] + + def remove_mallocs_once(self, graph): + """Perform one iteration of malloc removal.""" + remove_identical_vars(graph) + lifetimes = self.compute_lifetimes(graph) + progress = 0 + for info in lifetimes: + progress += self._try_inline_malloc(info) + return progress + + def remove_simple_mallocs(self, graph): + """Iteratively remove (inline) the mallocs that can be simplified away.""" + tot = 0 + while True: + count = self.remove_mallocs_once(graph) + if count: + log.malloc('%d simple mallocs removed in %r' % (count, graph.name)) + tot += count + else: + break + return tot + + +class LLTypeMallocRemover(BaseMallocRemover): - # must be only ever accessed via getfield/setfield/getsubstruct/ - # direct_fieldptr, or touched by keepalive or ptr_iszero/ptr_nonzero. - # Note that same_as and cast_pointer are not recorded in usepoints. - FIELD_ACCESS = dict.fromkeys(["getfield", + IDENTITY_OPS = ("same_as", "cast_pointer") + SUBSTRUCT_OPS = ("getsubstruct", "direct_fieldptr") + MALLOC_OP = "malloc" + FIELD_ACCESS = dict.fromkeys(["getfield", "setfield", "keepalive", "ptr_iszero", @@ -159,290 +267,240 @@ SUBSTRUCT_ACCESS = dict.fromkeys(["getsubstruct", "direct_fieldptr", "getarraysubstruct"]) - CHECK_ARRAY_INDEX = dict.fromkeys(["getarrayitem", "setarrayitem", "getarraysubstruct"]) - accessed_substructs = {} - for up in info.usepoints: - if up[0] != "op": - return False - kind, node, op, index = up - if index != 0: + def get_STRUCT(self, TYPE): + STRUCT = TYPE.TO + assert isinstance(STRUCT, lltype.GcStruct) + return STRUCT + + def do_substruct_access(self, op): + S = op.args[0].concretetype.TO + name = op.args[1].value + if not isinstance(name, str): # access by index + name = 'item%d' % (name,) + self.accessed_substructs[S, name] = True + + def equivalent_substruct(self, S, fieldname): + # we consider a pointer to a GcStruct S as equivalent to a + # pointer to a substructure 'S.fieldname' if it's the first + # inlined sub-GcStruct. As an extension we also allow a pointer + # to a GcStruct containing just one field to be equivalent to + # a pointer to that field only (although a mere cast_pointer + # would not allow casting). This is needed to malloc-remove + # the 'wrapper' GcStructs introduced by previous passes of + # malloc removal. + if not isinstance(S, lltype.GcStruct): return False - if op.opname in CHECK_ARRAY_INDEX: - if not isinstance(op.args[1], Constant): - return False # non-constant array index - if op.opname in FIELD_ACCESS: - pass # ok - elif op.opname in SUBSTRUCT_ACCESS: - S = op.args[0].concretetype.TO - name = op.args[1].value - if not isinstance(name, str): # access by index - name = 'item%d' % (name,) - accessed_substructs[S, name] = True - else: + if fieldname != S._names[0]: return False + FIELDTYPE = S._flds[fieldname] + if isinstance(FIELDTYPE, lltype.GcStruct): + if FIELDTYPE._hints.get('union'): + return False + return True + if len(S._names) == 1: + return True + return False - # must not remove mallocs of structures that have a RTTI with a destructor - - try: - destr_ptr = lltype.getRuntimeTypeInfo(STRUCT)._obj.destructor_funcptr - if destr_ptr: + def union_wrapper(self, S): + # check if 'S' is a GcStruct containing a single inlined *union* Struct + if not isinstance(S, lltype.GcStruct): return False - except (ValueError, AttributeError), e: - pass + assert not S._hints.get('union') # not supported: "GcUnion" + return (len(S._names) == 1 and + isinstance(S._flds[S._names[0]], lltype.Struct) and + S._flds[S._names[0]]._hints.get('union')) - # must not remove unions inlined as the only field of a GcStruct - if union_wrapper(STRUCT): - return False - - # success: replace each variable with a family of variables (one per field) - # 'flatnames' is a list of (STRUCTTYPE, fieldname_in_that_struct) that - # describes the list of variables that should replace the single - # malloc'ed pointer variable that we are about to remove. For primitive - # or pointer fields, the new corresponding variable just stores the - # actual value. For substructures, if pointers to them are "equivalent" - # to pointers to the parent structure (see equivalent_substruct()) then - # they are just merged, and flatnames will also list the fields within - # that substructure. Other substructures are replaced by a single new - # variable which is a pointer to a GcStruct-wrapper; each is malloc'ed - # individually, in an exploded way. (The next malloc removal pass will - # get rid of them again, in the typical case.) - flatnames = [] - flatconstants = {} - needsubmallocs = [] - newvarstype = {} # map {item-of-flatnames: concretetype} - direct_fieldptr_key = {} + def RTTI_dtor(self, STRUCT): + try: + destr_ptr = lltype.getRuntimeTypeInfo(STRUCT)._obj.destructor_funcptr + if destr_ptr: + return True + except (ValueError, AttributeError), e: + pass + return False - def flatten(S): + def flatten(self, S): start = 0 - if S._names and equivalent_substruct(S, S._names[0]): + if S._names and self.equivalent_substruct(S, S._names[0]): SUBTYPE = S._flds[S._names[0]] if isinstance(SUBTYPE, lltype.Struct): - flatten(SUBTYPE) + self.flatten(SUBTYPE) start = 1 else: ARRAY = lltype.FixedSizeArray(SUBTYPE, 1) - direct_fieldptr_key[ARRAY, 'item0'] = S, S._names[0] + self.direct_fieldptr_key[ARRAY, 'item0'] = S, S._names[0] for name in S._names[start:]: key = S, name FIELDTYPE = S._flds[name] - if key in accessed_substructs: - needsubmallocs.append(key) - flatnames.append(key) - newvarstype[key] = lltype.Ptr(lltype.GcStruct('wrapper', + if key in self.accessed_substructs: + self.needsubmallocs.append(key) + self.flatnames.append(key) + self.newvarstype[key] = lltype.Ptr(lltype.GcStruct('wrapper', ('data', FIELDTYPE))) elif not isinstance(FIELDTYPE, lltype.ContainerType): example = FIELDTYPE._defl() constant = Constant(example) constant.concretetype = FIELDTYPE - flatconstants[key] = constant - flatnames.append(key) - newvarstype[key] = FIELDTYPE + self.flatconstants[key] = constant + self.flatnames.append(key) + self.newvarstype[key] = FIELDTYPE #else: # the inlined substructure is never accessed, drop it - flatten(STRUCT) - assert len(direct_fieldptr_key) <= 1 - - def key_for_field_access(S, fldname): + def key_for_field_access(self, S, fldname): if isinstance(S, lltype.FixedSizeArray): if not isinstance(fldname, str): # access by index fldname = 'item%d' % (fldname,) try: - return direct_fieldptr_key[S, fldname] + return self.direct_fieldptr_key[S, fldname] except KeyError: pass return S, fldname - variables_by_block = {} - for block, var in info.variables: - vars = variables_by_block.setdefault(block, {}) - vars[var] = True - - count = [0] - - for block, vars in variables_by_block.items(): - - def flowin(var, newvarsmap): - # in this 'block', follow where the 'var' goes to and replace - # it by a flattened-out family of variables. This family is given - # by newvarsmap, whose keys are the 'flatnames'. - vars = {var: True} - last_removed_access = None + def flowin(self, block, count, var, newvarsmap): + # in this 'block', follow where the 'var' goes to and replace + # it by a flattened-out family of variables. This family is given + # by newvarsmap, whose keys are the 'flatnames'. + vars = {var: True} + last_removed_access = None - def list_newvars(): - return [newvarsmap[key] for key in flatnames] + def list_newvars(): + return [newvarsmap[key] for key in self.flatnames] - assert block.operations != () - newops = [] - for op in block.operations: - for arg in op.args[1:]: # should be the first arg only - assert arg not in vars - if op.args and op.args[0] in vars: - if op.opname in ("getfield", "getarrayitem"): - S = op.args[0].concretetype.TO - fldname = op.args[1].value - key = key_for_field_access(S, fldname) - if key in accessed_substructs: - c_name = Constant('data', lltype.Void) - newop = SpaceOperation("getfield", - [newvarsmap[key], c_name], - op.result) - else: - newop = SpaceOperation("same_as", - [newvarsmap[key]], - op.result) + assert block.operations != () + newops = [] + for op in block.operations: + for arg in op.args[1:]: # should be the first arg only + assert arg not in vars + if op.args and op.args[0] in vars: + if op.opname in ("getfield", "getarrayitem"): + S = op.args[0].concretetype.TO + fldname = op.args[1].value + key = self.key_for_field_access(S, fldname) + if key in self.accessed_substructs: + c_name = Constant('data', lltype.Void) + newop = SpaceOperation("getfield", + [newvarsmap[key], c_name], + op.result) + else: + newop = SpaceOperation("same_as", + [newvarsmap[key]], + op.result) + newops.append(newop) + last_removed_access = len(newops) + elif op.opname in ("setfield", "setarrayitem"): + S = op.args[0].concretetype.TO + fldname = op.args[1].value + key = self.key_for_field_access(S, fldname) + assert key in newvarsmap + if key in self.accessed_substructs: + c_name = Constant('data', lltype.Void) + newop = SpaceOperation("setfield", + [newvarsmap[key], c_name, op.args[2]], + op.result) newops.append(newop) - last_removed_access = len(newops) - elif op.opname in ("setfield", "setarrayitem"): - S = op.args[0].concretetype.TO - fldname = op.args[1].value - key = key_for_field_access(S, fldname) - assert key in newvarsmap - if key in accessed_substructs: - c_name = Constant('data', lltype.Void) - newop = SpaceOperation("setfield", - [newvarsmap[key], c_name, op.args[2]], - op.result) - newops.append(newop) - else: - newvarsmap[key] = op.args[2] - last_removed_access = len(newops) - elif op.opname in ("same_as", "cast_pointer"): + else: + newvarsmap[key] = op.args[2] + last_removed_access = len(newops) + elif op.opname in ("same_as", "cast_pointer"): + assert op.result not in vars + vars[op.result] = True + # Consider the two pointers (input and result) as + # equivalent. We can, and indeed must, use the same + # flattened list of variables for both, as a "setfield" + # via one pointer must be reflected in the other. + elif op.opname == 'keepalive': + last_removed_access = len(newops) + elif op.opname in ("getsubstruct", "getarraysubstruct", + "direct_fieldptr"): + S = op.args[0].concretetype.TO + fldname = op.args[1].value + if op.opname == "getarraysubstruct": + fldname = 'item%d' % fldname + equiv = self.equivalent_substruct(S, fldname) + if equiv: + # exactly like a cast_pointer assert op.result not in vars vars[op.result] = True - # Consider the two pointers (input and result) as - # equivalent. We can, and indeed must, use the same - # flattened list of variables for both, as a "setfield" - # via one pointer must be reflected in the other. - elif op.opname == 'keepalive': - last_removed_access = len(newops) - elif op.opname in ("getsubstruct", "getarraysubstruct", - "direct_fieldptr"): - S = op.args[0].concretetype.TO - fldname = op.args[1].value - if op.opname == "getarraysubstruct": - fldname = 'item%d' % fldname - equiv = equivalent_substruct(S, fldname) - if equiv: - # exactly like a cast_pointer - assert op.result not in vars - vars[op.result] = True - else: - # do it with a getsubstruct on the independently - # malloc'ed GcStruct - if op.opname == "direct_fieldptr": - opname = "direct_fieldptr" - else: - opname = "getsubstruct" - v = newvarsmap[S, fldname] - cname = Constant('data', lltype.Void) - newop = SpaceOperation(opname, - [v, cname], - op.result) - newops.append(newop) - elif op.opname in ("ptr_iszero", "ptr_nonzero"): - # we know the pointer is not NULL if it comes from - # a successful malloc - c = Constant(op.opname == "ptr_nonzero", lltype.Bool) - newop = SpaceOperation('same_as', [c], op.result) - newops.append(newop) else: - raise AssertionError, op.opname - elif op.result in vars: - assert op.opname == "malloc" - assert vars == {var: True} - progress = True - # drop the "malloc" operation - newvarsmap = flatconstants.copy() # zero initial values - # if there are substructures, they are now individually - # malloc'ed in an exploded way. (They will typically be - # removed again by the next malloc removal pass.) - for key in needsubmallocs: - v = Variable() - v.concretetype = newvarstype[key] - c = Constant(v.concretetype.TO, lltype.Void) - if c.value == op.args[0].value: - progress = False # replacing a malloc with - # the same malloc! - newop = SpaceOperation("malloc", [c], v) + # do it with a getsubstruct on the independently + # malloc'ed GcStruct + if op.opname == "direct_fieldptr": + opname = "direct_fieldptr" + else: + opname = "getsubstruct" + v = newvarsmap[S, fldname] + cname = Constant('data', lltype.Void) + newop = SpaceOperation(opname, + [v, cname], + op.result) newops.append(newop) - newvarsmap[key] = v - count[0] += progress + elif op.opname in ("ptr_iszero", "ptr_nonzero"): + # we know the pointer is not NULL if it comes from + # a successful malloc + c = Constant(op.opname == "ptr_nonzero", lltype.Bool) + newop = SpaceOperation('same_as', [c], op.result) + newops.append(newop) else: - newops.append(op) + raise AssertionError, op.opname + elif op.result in vars: + assert op.opname == self.MALLOC_OP + assert vars == {var: True} + progress = True + # drop the "malloc" operation + newvarsmap = self.flatconstants.copy() # zero initial values + # if there are substructures, they are now individually + # malloc'ed in an exploded way. (They will typically be + # removed again by the next malloc removal pass.) + for key in self.needsubmallocs: + v = Variable() + v.concretetype = self.newvarstype[key] + c = Constant(v.concretetype.TO, lltype.Void) + if c.value == op.args[0].value: + progress = False # replacing a malloc with + # the same malloc! + newop = SpaceOperation(self.MALLOC_OP, [c], v) + newops.append(newop) + newvarsmap[key] = v + count[0] += progress + else: + newops.append(op) - assert block.exitswitch not in vars + assert block.exitswitch not in vars - for link in block.exits: - newargs = [] - for arg in link.args: - if arg in vars: - newargs += list_newvars() - else: - newargs.append(arg) - link.args[:] = newargs - - if last_removed_access is not None: - keepalives = [] - for v in list_newvars(): - T = v.concretetype - if isinstance(T, lltype.Ptr) and T._needsgc(): - v0 = Variable() - v0.concretetype = lltype.Void - newop = SpaceOperation('keepalive', [v], v0) - keepalives.append(newop) - newops[last_removed_access:last_removed_access] = keepalives - - block.operations[:] = newops - - # look for variables arriving from outside the block - for var in vars: - if var in block.inputargs: - i = block.inputargs.index(var) - newinputargs = block.inputargs[:i] - newvarsmap = {} - for key in flatnames: - newvar = Variable() - newvar.concretetype = newvarstype[key] - newvarsmap[key] = newvar - newinputargs.append(newvar) - newinputargs += block.inputargs[i+1:] - block.inputargs[:] = newinputargs - assert var not in block.inputargs - flowin(var, newvarsmap) + for link in block.exits: + newargs = [] + for arg in link.args: + if arg in vars: + newargs += list_newvars() + else: + newargs.append(arg) + link.args[:] = newargs - # look for variables created inside the block by a malloc - vars_created_here = [] - for op in block.operations: - if op.opname == "malloc" and op.result in vars: - vars_created_here.append(op.result) - for var in vars_created_here: - flowin(var, newvarsmap=None) - - return count[0] - -def remove_mallocs_once(graph): - """Perform one iteration of malloc removal.""" - remove_identical_vars(graph) - lifetimes = compute_lifetimes(graph) - progress = 0 - for info in lifetimes: - progress += _try_inline_malloc(info) - return progress - -def remove_simple_mallocs(graph): - """Iteratively remove (inline) the mallocs that can be simplified away.""" - tot = 0 - while True: - count = remove_mallocs_once(graph) - if count: - log.malloc('%d simple mallocs removed in %r' % (count, graph.name)) - tot += count - else: - break - return tot + if last_removed_access is not None: + keepalives = [] + for v in list_newvars(): + T = v.concretetype + if isinstance(T, lltype.Ptr) and T._needsgc(): + v0 = Variable() + v0.concretetype = lltype.Void + newop = SpaceOperation('keepalive', [v], v0) + keepalives.append(newop) + newops[last_removed_access:last_removed_access] = keepalives + + block.operations[:] = newops + +class OOTypeMallocRemover(BaseMallocRemover): + pass # TODO + +def remove_simple_mallocs(graph, type_system='lltype'): + if type_system == 'lltype': + remover = LLTypeMallocRemover() + else: + remover = OOTypeMallocRemover() + return remover.remove_simple_mallocs(graph) Modified: pypy/dist/pypy/translator/backendopt/test/test_malloc.py ============================================================================== --- pypy/dist/pypy/translator/backendopt/test/test_malloc.py (original) +++ pypy/dist/pypy/translator/backendopt/test/test_malloc.py Fri Dec 29 14:34:40 2006 @@ -1,6 +1,5 @@ import py -from pypy.translator.backendopt.malloc import remove_mallocs_once -from pypy.translator.backendopt.malloc import union_wrapper +from pypy.translator.backendopt.malloc import LLTypeMallocRemover from pypy.translator.backendopt.inline import inline_function from pypy.translator.backendopt.all import backend_optimizations from pypy.translator.translator import TranslationContext, graphof @@ -13,6 +12,7 @@ def check_malloc_removed(graph): + remover = LLTypeMallocRemover() checkgraph(graph) count1 = count2 = 0 for node in flatten(graph): @@ -20,7 +20,7 @@ for op in node.operations: if op.opname == 'malloc': S = op.args[0].value - if not union_wrapper(S): # union wrappers are fine + if not remover.union_wrapper(S): # union wrappers are fine count1 += 1 if op.opname in ('direct_call', 'indirect_call'): count2 += 1 @@ -28,6 +28,7 @@ assert count2 == 0 # number of calls left def check(fn, signature, args, expected_result, must_be_removed=True): + remover = LLTypeMallocRemover() t = TranslationContext() t.buildannotator().build_types(fn, signature) t.buildrtyper().specialize() @@ -37,7 +38,7 @@ # to detect missing keepalives and broken intermediate graphs, # we do the loop ourselves instead of calling remove_simple_mallocs() while True: - progress = remove_mallocs_once(graph) + progress = remover.remove_mallocs_once(graph) simplify.transform_dead_op_vars_in_blocks(list(graph.iterblocks())) if progress and option.view: t.view() From antocuni at codespeak.net Fri Dec 29 14:47:08 2006 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Fri, 29 Dec 2006 14:47:08 +0100 (CET) Subject: [pypy-svn] r36036 - pypy/dist/pypy/translator/backendopt Message-ID: <20061229134708.03BEB10090@code0.codespeak.net> Author: antocuni Date: Fri Dec 29 14:47:08 2006 New Revision: 36036 Modified: pypy/dist/pypy/translator/backendopt/malloc.py Log: Other steps in porting malloc removal to ootype. Now BaseMallocRemover should be free from any explicit reference to lltype. Modified: pypy/dist/pypy/translator/backendopt/malloc.py ============================================================================== --- pypy/dist/pypy/translator/backendopt/malloc.py (original) +++ pypy/dist/pypy/translator/backendopt/malloc.py Fri Dec 29 14:47:08 2006 @@ -30,10 +30,10 @@ def get_STRUCT(self, TYPE): raise NotImplementedError - def do_substruct_access(self, op): + def visit_substruct_op(self, node, union, op): raise NotImplementedError - def equivalent_substruct(self, S, fieldname): + def do_substruct_access(self, op): raise NotImplementedError def union_wrapper(self, S): @@ -91,10 +91,7 @@ union(node, op.args[0], node, op.result) continue if op.opname in self.SUBSTRUCT_OPS: - S = op.args[0].concretetype.TO - if self.equivalent_substruct(S, op.args[1].value): - # assumed to be similar to a cast_pointer - union(node, op.args[0], node, op.result) + if self.visit_substruct_op(node, union, op): continue for i in range(len(op.args)): if isinstance(op.args[i], Variable): @@ -276,6 +273,14 @@ assert isinstance(STRUCT, lltype.GcStruct) return STRUCT + def visit_substruct_op(self, node, union, op): + S = op.args[0].concretetype.TO + if self.equivalent_substruct(S, op.args[1].value): + # assumed to be similar to a cast_pointer + union(node, op.args[0], node, op.result) + return True + return False + def do_substruct_access(self, op): S = op.args[0].concretetype.TO name = op.args[1].value From antocuni at codespeak.net Fri Dec 29 16:45:23 2006 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Fri, 29 Dec 2006 16:45:23 +0100 (CET) Subject: [pypy-svn] r36037 - in pypy/dist/pypy/translator/backendopt: . test Message-ID: <20061229154523.812161009D@code0.codespeak.net> Author: antocuni Date: Fri Dec 29 16:45:19 2006 New Revision: 36037 Modified: pypy/dist/pypy/translator/backendopt/all.py pypy/dist/pypy/translator/backendopt/malloc.py pypy/dist/pypy/translator/backendopt/test/test_malloc.py Log: Malloc removal works with ootype now! Modified: pypy/dist/pypy/translator/backendopt/all.py ============================================================================== --- pypy/dist/pypy/translator/backendopt/all.py (original) +++ pypy/dist/pypy/translator/backendopt/all.py Fri Dec 29 16:45:19 2006 @@ -92,6 +92,7 @@ def inline_malloc_removal_phase(config, translator, graphs, inline_threshold, call_count_pred=None): + type_system = translator.rtyper.type_system.name log.inlining("phase with threshold factor: %s" % inline_threshold) # inline functions in each other @@ -113,7 +114,7 @@ if config.mallocs: tot = 0 for graph in graphs: - count = remove_simple_mallocs(graph) + count = remove_simple_mallocs(graph, type_system) if count: # remove typical leftovers from malloc removal removenoops.remove_same_as(graph) Modified: pypy/dist/pypy/translator/backendopt/malloc.py ============================================================================== --- pypy/dist/pypy/translator/backendopt/malloc.py (original) +++ pypy/dist/pypy/translator/backendopt/malloc.py Fri Dec 29 16:45:19 2006 @@ -2,6 +2,7 @@ from pypy.objspace.flow.model import SpaceOperation, traverse from pypy.tool.algo.unionfind import UnionFind from pypy.rpython.lltypesystem import lltype +from pypy.rpython.ootypesystem import ootype from pypy.translator.simplify import remove_identical_vars from pypy.translator.backendopt.support import log @@ -49,7 +50,58 @@ raise NotImplementedError def flowin(self, block, count, var, newvarsmap): - raise NotImplementedError + # in this 'block', follow where the 'var' goes to and replace + # it by a flattened-out family of variables. This family is given + # by newvarsmap, whose keys are the 'flatnames'. + vars = {var: True} + self.last_removed_access = None + + def list_newvars(): + return [newvarsmap[key] for key in self.flatnames] + + assert block.operations != () + self.newops = [] + for op in block.operations: + for arg in op.args[1:]: # should be the first arg only + assert arg not in vars + if op.args and op.args[0] in vars: + self.flowin_op(op, vars, newvarsmap) + elif op.result in vars: + assert op.opname == self.MALLOC_OP + assert vars == {var: True} + progress = True + # drop the "malloc" operation + newvarsmap = self.flatconstants.copy() # zero initial values + # if there are substructures, they are now individually + # malloc'ed in an exploded way. (They will typically be + # removed again by the next malloc removal pass.) + for key in self.needsubmallocs: + v = Variable() + v.concretetype = self.newvarstype[key] + c = Constant(v.concretetype.TO, lltype.Void) + if c.value == op.args[0].value: + progress = False # replacing a malloc with + # the same malloc! + newop = SpaceOperation(self.MALLOC_OP, [c], v) + self.newops.append(newop) + newvarsmap[key] = v + count[0] += progress + else: + self.newops.append(op) + + assert block.exitswitch not in vars + + for link in block.exits: + newargs = [] + for arg in link.args: + if arg in vars: + newargs += list_newvars() + else: + newargs.append(arg) + link.args[:] = newargs + + self.insert_keepalives(list_newvars()) + block.operations[:] = self.newops def compute_lifetimes(self, graph): """Compute the static data flow of the graph: returns a list of LifeTime @@ -367,141 +419,170 @@ pass return S, fldname - def flowin(self, block, count, var, newvarsmap): - # in this 'block', follow where the 'var' goes to and replace - # it by a flattened-out family of variables. This family is given - # by newvarsmap, whose keys are the 'flatnames'. - vars = {var: True} - last_removed_access = None - - def list_newvars(): - return [newvarsmap[key] for key in self.flatnames] - - assert block.operations != () - newops = [] - for op in block.operations: - for arg in op.args[1:]: # should be the first arg only - assert arg not in vars - if op.args and op.args[0] in vars: - if op.opname in ("getfield", "getarrayitem"): - S = op.args[0].concretetype.TO - fldname = op.args[1].value - key = self.key_for_field_access(S, fldname) - if key in self.accessed_substructs: - c_name = Constant('data', lltype.Void) - newop = SpaceOperation("getfield", - [newvarsmap[key], c_name], - op.result) - else: - newop = SpaceOperation("same_as", - [newvarsmap[key]], - op.result) - newops.append(newop) - last_removed_access = len(newops) - elif op.opname in ("setfield", "setarrayitem"): - S = op.args[0].concretetype.TO - fldname = op.args[1].value - key = self.key_for_field_access(S, fldname) - assert key in newvarsmap - if key in self.accessed_substructs: - c_name = Constant('data', lltype.Void) - newop = SpaceOperation("setfield", - [newvarsmap[key], c_name, op.args[2]], - op.result) - newops.append(newop) - else: - newvarsmap[key] = op.args[2] - last_removed_access = len(newops) - elif op.opname in ("same_as", "cast_pointer"): - assert op.result not in vars - vars[op.result] = True - # Consider the two pointers (input and result) as - # equivalent. We can, and indeed must, use the same - # flattened list of variables for both, as a "setfield" - # via one pointer must be reflected in the other. - elif op.opname == 'keepalive': - last_removed_access = len(newops) - elif op.opname in ("getsubstruct", "getarraysubstruct", - "direct_fieldptr"): - S = op.args[0].concretetype.TO - fldname = op.args[1].value - if op.opname == "getarraysubstruct": - fldname = 'item%d' % fldname - equiv = self.equivalent_substruct(S, fldname) - if equiv: - # exactly like a cast_pointer - assert op.result not in vars - vars[op.result] = True - else: - # do it with a getsubstruct on the independently - # malloc'ed GcStruct - if op.opname == "direct_fieldptr": - opname = "direct_fieldptr" - else: - opname = "getsubstruct" - v = newvarsmap[S, fldname] - cname = Constant('data', lltype.Void) - newop = SpaceOperation(opname, - [v, cname], - op.result) - newops.append(newop) - elif op.opname in ("ptr_iszero", "ptr_nonzero"): - # we know the pointer is not NULL if it comes from - # a successful malloc - c = Constant(op.opname == "ptr_nonzero", lltype.Bool) - newop = SpaceOperation('same_as', [c], op.result) - newops.append(newop) - else: - raise AssertionError, op.opname - elif op.result in vars: - assert op.opname == self.MALLOC_OP - assert vars == {var: True} - progress = True - # drop the "malloc" operation - newvarsmap = self.flatconstants.copy() # zero initial values - # if there are substructures, they are now individually - # malloc'ed in an exploded way. (They will typically be - # removed again by the next malloc removal pass.) - for key in self.needsubmallocs: - v = Variable() - v.concretetype = self.newvarstype[key] - c = Constant(v.concretetype.TO, lltype.Void) - if c.value == op.args[0].value: - progress = False # replacing a malloc with - # the same malloc! - newop = SpaceOperation(self.MALLOC_OP, [c], v) - newops.append(newop) - newvarsmap[key] = v - count[0] += progress + def flowin_op(self, op, vars, newvarsmap): + if op.opname in ("getfield", "getarrayitem"): + S = op.args[0].concretetype.TO + fldname = op.args[1].value + key = self.key_for_field_access(S, fldname) + if key in self.accessed_substructs: + c_name = Constant('data', lltype.Void) + newop = SpaceOperation("getfield", + [newvarsmap[key], c_name], + op.result) else: - newops.append(op) - - assert block.exitswitch not in vars - - for link in block.exits: - newargs = [] - for arg in link.args: - if arg in vars: - newargs += list_newvars() + newop = SpaceOperation("same_as", + [newvarsmap[key]], + op.result) + self.newops.append(newop) + self.last_removed_access = len(self.newops) + elif op.opname in ("setfield", "setarrayitem"): + S = op.args[0].concretetype.TO + fldname = op.args[1].value + key = self.key_for_field_access(S, fldname) + assert key in newvarsmap + if key in self.accessed_substructs: + c_name = Constant('data', lltype.Void) + newop = SpaceOperation("setfield", + [newvarsmap[key], c_name, op.args[2]], + op.result) + self.newops.append(newop) + else: + newvarsmap[key] = op.args[2] + self.last_removed_access = len(self.newops) + elif op.opname in ("same_as", "cast_pointer"): + assert op.result not in vars + vars[op.result] = True + # Consider the two pointers (input and result) as + # equivalent. We can, and indeed must, use the same + # flattened list of variables for both, as a "setfield" + # via one pointer must be reflected in the other. + elif op.opname == 'keepalive': + self.last_removed_access = len(self.newops) + elif op.opname in ("getsubstruct", "getarraysubstruct", + "direct_fieldptr"): + S = op.args[0].concretetype.TO + fldname = op.args[1].value + if op.opname == "getarraysubstruct": + fldname = 'item%d' % fldname + equiv = self.equivalent_substruct(S, fldname) + if equiv: + # exactly like a cast_pointer + assert op.result not in vars + vars[op.result] = True + else: + # do it with a getsubstruct on the independently + # malloc'ed GcStruct + if op.opname == "direct_fieldptr": + opname = "direct_fieldptr" else: - newargs.append(arg) - link.args[:] = newargs - - if last_removed_access is not None: + opname = "getsubstruct" + v = newvarsmap[S, fldname] + cname = Constant('data', lltype.Void) + newop = SpaceOperation(opname, + [v, cname], + op.result) + self.newops.append(newop) + elif op.opname in ("ptr_iszero", "ptr_nonzero"): + # we know the pointer is not NULL if it comes from + # a successful malloc + c = Constant(op.opname == "ptr_nonzero", lltype.Bool) + newop = SpaceOperation('same_as', [c], op.result) + self.newops.append(newop) + else: + raise AssertionError, op.opname + + + def insert_keepalives(self, newvars): + if self.last_removed_access is not None: keepalives = [] - for v in list_newvars(): + for v in newvars: T = v.concretetype if isinstance(T, lltype.Ptr) and T._needsgc(): v0 = Variable() v0.concretetype = lltype.Void newop = SpaceOperation('keepalive', [v], v0) keepalives.append(newop) - newops[last_removed_access:last_removed_access] = keepalives - - block.operations[:] = newops + self.newops[self.last_removed_access:self.last_removed_access] = keepalives class OOTypeMallocRemover(BaseMallocRemover): - pass # TODO + + IDENTITY_OPS = ('same_as', 'ooupcast', 'oodowncast') + SUBSTRUCT_OPS = () + MALLOC_OP = 'new' + FIELD_ACCESS = dict.fromkeys(["oogetfield", + "oosetfield", + "oononnull", + #"oois", # ??? + #"instanceof", # ??? + ]) + SUBSTRUCT_ACCESS = {} + CHECK_ARRAY_INDEX = {} + + def get_STRUCT(self, TYPE): + return TYPE + + def union_wrapper(self, S): + return False + + def RTTI_dtor(self, STRUCT): + return False + + def _get_fields(self, TYPE): + if isinstance(TYPE, ootype.Record): + return TYPE._fields + elif isinstance(TYPE, ootype.Instance): + return TYPE._allfields() + else: + assert False + + def flatten(self, TYPE): + for name, (FIELDTYPE, default) in self._get_fields(TYPE).iteritems(): + key = TYPE, name + example = FIELDTYPE._defl() + constant = Constant(example) + constant.concretetype = FIELDTYPE + self.flatconstants[key] = constant + self.flatnames.append(key) + self.newvarstype[key] = FIELDTYPE + + def key_for_field_access(self, S, fldname): + return S, fldname + + def flowin_op(self, op, vars, newvarsmap): + if op.opname == "oogetfield": + S = op.args[0].concretetype + fldname = op.args[1].value + key = self.key_for_field_access(S, fldname) + newop = SpaceOperation("same_as", + [newvarsmap[key]], + op.result) + self.newops.append(newop) + last_removed_access = len(self.newops) + elif op.opname == "oosetfield": + S = op.args[0].concretetype + fldname = op.args[1].value + key = self.key_for_field_access(S, fldname) + assert key in newvarsmap + newvarsmap[key] = op.args[2] + last_removed_access = len(self.newops) + elif op.opname in ("same_as", "oodowncast", "ooupcast"): + assert op.result not in vars + vars[op.result] = True + # Consider the two pointers (input and result) as + # equivalent. We can, and indeed must, use the same + # flattened list of variables for both, as a "setfield" + # via one pointer must be reflected in the other. + elif op.opname == "oononnull": + # we know the pointer is not NULL if it comes from + # a successful malloc + c = Constant(True, lltype.Bool) + newop = SpaceOperation('same_as', [c], op.result) + self.newops.append(newop) + else: + raise AssertionError, op.opname + + def insert_keepalives(self, newvars): + pass def remove_simple_mallocs(graph, type_system='lltype'): if type_system == 'lltype': Modified: pypy/dist/pypy/translator/backendopt/test/test_malloc.py ============================================================================== --- pypy/dist/pypy/translator/backendopt/test/test_malloc.py (original) +++ pypy/dist/pypy/translator/backendopt/test/test_malloc.py Fri Dec 29 16:45:19 2006 @@ -1,5 +1,5 @@ import py -from pypy.translator.backendopt.malloc import LLTypeMallocRemover +from pypy.translator.backendopt.malloc import LLTypeMallocRemover, OOTypeMallocRemover from pypy.translator.backendopt.inline import inline_function from pypy.translator.backendopt.all import backend_optimizations from pypy.translator.translator import TranslationContext, graphof @@ -7,311 +7,336 @@ from pypy.objspace.flow.model import checkgraph, flatten, Block, mkentrymap from pypy.rpython.llinterp import LLInterpreter from pypy.rpython.lltypesystem import lltype, llmemory +from pypy.rpython.ootypesystem import ootype from pypy.rlib import objectmodel from pypy.conftest import option - -def check_malloc_removed(graph): - remover = LLTypeMallocRemover() - checkgraph(graph) - count1 = count2 = 0 - for node in flatten(graph): - if isinstance(node, Block): - for op in node.operations: - if op.opname == 'malloc': - S = op.args[0].value - if not remover.union_wrapper(S): # union wrappers are fine - count1 += 1 - if op.opname in ('direct_call', 'indirect_call'): - count2 += 1 - assert count1 == 0 # number of mallocs left - assert count2 == 0 # number of calls left - -def check(fn, signature, args, expected_result, must_be_removed=True): - remover = LLTypeMallocRemover() - t = TranslationContext() - t.buildannotator().build_types(fn, signature) - t.buildrtyper().specialize() - graph = graphof(t, fn) - if option.view: - t.view() - # to detect missing keepalives and broken intermediate graphs, - # we do the loop ourselves instead of calling remove_simple_mallocs() - while True: - progress = remover.remove_mallocs_once(graph) - simplify.transform_dead_op_vars_in_blocks(list(graph.iterblocks())) - if progress and option.view: +class BaseMallocRemovalTest(object): + type_system = None + MallocRemover = None + + def _skip_oo(self, msg): + if self.type_system == 'ootype': + py.test.skip(msg) + + def check_malloc_removed(self, graph): + remover = self.MallocRemover() + checkgraph(graph) + count1 = count2 = 0 + for node in flatten(graph): + if isinstance(node, Block): + for op in node.operations: + if op.opname == self.MallocRemover.MALLOC_OP: + S = op.args[0].value + if not remover.union_wrapper(S): # union wrappers are fine + count1 += 1 + if op.opname in ('direct_call', 'indirect_call'): + count2 += 1 + assert count1 == 0 # number of mallocs left + assert count2 == 0 # number of calls left + + def check(self, fn, signature, args, expected_result, must_be_removed=True): + remover = self.MallocRemover() + t = TranslationContext() + t.buildannotator().build_types(fn, signature) + t.buildrtyper(type_system=self.type_system).specialize() + graph = graphof(t, fn) + if option.view: t.view() - if expected_result is not Ellipsis: - interp = LLInterpreter(t.rtyper) - res = interp.eval_graph(graph, args) - assert res == expected_result - if not progress: - break - if must_be_removed: - check_malloc_removed(graph) - return graph - - -def test_fn1(): - def fn1(x, y): - if x > 0: - t = x+y, x-y - else: - t = x-y, x+y - s, d = t - return s*d - check(fn1, [int, int], [15, 10], 125) - -def test_fn2(): - class T: - pass - def fn2(x, y): - t = T() - t.x = x - t.y = y - if x > 0: - return t.x + t.y - else: - return t.x - t.y - check(fn2, [int, int], [-6, 7], -13) - -def test_fn3(): - def fn3(x): - a, ((b, c), d, e) = x+1, ((x+2, x+3), x+4, x+5) - return a+b+c+d+e - check(fn3, [int], [10], 65) - -def test_fn4(): - class A: - pass - class B(A): - pass - def fn4(i): - a = A() - b = B() - a.b = b - b.i = i - return a.b.i - check(fn4, [int], [42], 42) - -def test_fn5(): - class A: - attr = 666 - class B(A): - attr = 42 - def fn5(): - b = B() - return b.attr - check(fn5, [], [], 42) - -def test_aliasing(): - class A: - pass - def fn6(n): - a1 = A() - a1.x = 5 - a2 = A() - a2.x = 6 - if n > 0: - a = a1 - else: - a = a2 - a.x = 12 - return a1.x - check(fn6, [int], [1], 12, must_be_removed=False) - -def test_with_keepalive(): - from pypy.rlib.objectmodel import keepalive_until_here - def fn1(x, y): - if x > 0: - t = x+y, x-y - else: - t = x-y, x+y - s, d = t - keepalive_until_here(t) - return s*d - check(fn1, [int, int], [15, 10], 125) - -def test_dont_remove_with__del__(): - import os - delcalls = [0] - class A(object): - nextid = 0 - def __init__(self): - self.id = self.nextid - self.nextid += 1 - - def __del__(self): - delcalls[0] += 1 - os.write(1, "__del__\n") - - def f(x=int): - a = A() - i = 0 - while i < x: + # to detect missing keepalives and broken intermediate graphs, + # we do the loop ourselves instead of calling remove_simple_mallocs() + while True: + progress = remover.remove_mallocs_once(graph) + simplify.transform_dead_op_vars_in_blocks(list(graph.iterblocks())) + if progress and option.view: + t.view() + if expected_result is not Ellipsis: + interp = LLInterpreter(t.rtyper) + res = interp.eval_graph(graph, args) + assert res == expected_result + if not progress: + break + if must_be_removed: + self.check_malloc_removed(graph) + return graph + + def test_fn1(self): + def fn1(x, y): + if x > 0: + t = x+y, x-y + else: + t = x-y, x+y + s, d = t + return s*d + self.check(fn1, [int, int], [15, 10], 125) + + def test_fn2(self): + class T: + pass + def fn2(x, y): + t = T() + t.x = x + t.y = y + if x > 0: + return t.x + t.y + else: + return t.x - t.y + self.check(fn2, [int, int], [-6, 7], -13) + + def test_fn3(self): + def fn3(x): + a, ((b, c), d, e) = x+1, ((x+2, x+3), x+4, x+5) + return a+b+c+d+e + self.check(fn3, [int], [10], 65) + + def test_fn4(self): + class A: + pass + class B(A): + pass + def fn4(i): + a = A() + b = B() + a.b = b + b.i = i + return a.b.i + self.check(fn4, [int], [42], 42) + + def test_fn5(self): + self._skip_oo('It will work as soon as trivial oosend are inlined') + class A: + attr = 666 + class B(A): + attr = 42 + def fn5(): + b = B() + return b.attr + self.check(fn5, [], [], 42) + + def test_aliasing(self): + class A: + pass + def fn6(n): + a1 = A() + a1.x = 5 + a2 = A() + a2.x = 6 + if n > 0: + a = a1 + else: + a = a2 + a.x = 12 + return a1.x + self.check(fn6, [int], [1], 12, must_be_removed=False) + + + +class TestLLTypeMallocRemoval(BaseMallocRemovalTest): + type_system = 'lltype' + MallocRemover = LLTypeMallocRemover + + def test_with_keepalive(self): + from pypy.rlib.objectmodel import keepalive_until_here + def fn1(x, y): + if x > 0: + t = x+y, x-y + else: + t = x-y, x+y + s, d = t + keepalive_until_here(t) + return s*d + self.check(fn1, [int, int], [15, 10], 125) + + def test_dont_remove_with__del__(self): + import os + delcalls = [0] + class A(object): + nextid = 0 + def __init__(self): + self.id = self.nextid + self.nextid += 1 + + def __del__(self): + delcalls[0] += 1 + os.write(1, "__del__\n") + + def f(x=int): + a = A() + i = 0 + while i < x: + a = A() + os.write(1, str(delcalls[0]) + "\n") + i += 1 + return 1 + t = TranslationContext() + t.buildannotator().build_types(f, [int]) + t.buildrtyper().specialize() + graph = graphof(t, f) + backend_optimizations(t) + op = graph.startblock.exits[0].target.exits[1].target.operations[0] + assert op.opname == "malloc" + + def test_add_keepalives(self): + class A: + pass + SMALL = lltype.Struct('SMALL', ('x', lltype.Signed)) + BIG = lltype.GcStruct('BIG', ('z', lltype.Signed), ('s', SMALL)) + def fn7(i): + big = lltype.malloc(BIG) a = A() - os.write(1, str(delcalls[0]) + "\n") - i += 1 - return 1 - t = TranslationContext() - t.buildannotator().build_types(f, [int]) - t.buildrtyper().specialize() - graph = graphof(t, f) - backend_optimizations(t) - op = graph.startblock.exits[0].target.exits[1].target.operations[0] - assert op.opname == "malloc" - -def test_add_keepalives(): - class A: - pass - SMALL = lltype.Struct('SMALL', ('x', lltype.Signed)) - BIG = lltype.GcStruct('BIG', ('z', lltype.Signed), ('s', SMALL)) - def fn7(i): - big = lltype.malloc(BIG) - a = A() - a.big = big - a.small = big.s - a.small.x = 0 - while i > 0: - a.small.x += i - i -= 1 - return a.small.x - check(fn7, [int], [10], 55, must_be_removed=False) - -def test_getsubstruct(): - SMALL = lltype.Struct('SMALL', ('x', lltype.Signed)) - BIG = lltype.GcStruct('BIG', ('z', lltype.Signed), ('s', SMALL)) - - def fn(n1, n2): - b = lltype.malloc(BIG) - b.z = n1 - b.s.x = n2 - return b.z - b.s.x - - check(fn, [int, int], [100, 58], 42) - -def test_fixedsizearray(): - A = lltype.FixedSizeArray(lltype.Signed, 3) - S = lltype.GcStruct('S', ('a', A)) - - def fn(n1, n2): - s = lltype.malloc(S) - a = s.a - a[0] = n1 - a[2] = n2 - return a[0]-a[2] - - check(fn, [int, int], [100, 42], 58) - -def test_wrapper_cannot_be_removed(): - SMALL = lltype.OpaqueType('SMALL') - BIG = lltype.GcStruct('BIG', ('z', lltype.Signed), ('s', SMALL)) - - def g(small): - return -1 - def fn(): - b = lltype.malloc(BIG) - g(b.s) - - check(fn, [], [], None, must_be_removed=False) - -def test_direct_fieldptr(): - S = lltype.GcStruct('S', ('x', lltype.Signed)) - - def fn(): - s = lltype.malloc(S) - s.x = 11 - p = lltype.direct_fieldptr(s, 'x') - return p[0] - - check(fn, [], [], 11) - -def test_direct_fieldptr_2(): - T = lltype.GcStruct('T', ('z', lltype.Signed)) - S = lltype.GcStruct('S', ('t', T), - ('x', lltype.Signed), - ('y', lltype.Signed)) - def fn(): - s = lltype.malloc(S) - s.x = 10 - s.t.z = 1 - px = lltype.direct_fieldptr(s, 'x') - py = lltype.direct_fieldptr(s, 'y') - pz = lltype.direct_fieldptr(s.t, 'z') - py[0] = 31 - return px[0] + s.y + pz[0] - - check(fn, [], [], 42) - -def test_getarraysubstruct(): - U = lltype.Struct('U', ('n', lltype.Signed)) - for length in [1, 2]: - S = lltype.GcStruct('S', ('a', lltype.FixedSizeArray(U, length))) - for index in range(length): - - def fn(): - s = lltype.malloc(S) - s.a[index].n = 12 - return s.a[index].n - check(fn, [], [], 12) - -def test_ptr_nonzero(): - S = lltype.GcStruct('S') - def fn(): - s = lltype.malloc(S) - return bool(s) - check(fn, [], [], True) - -def test_substruct_not_accessed(): - SMALL = lltype.Struct('SMALL', ('x', lltype.Signed)) - BIG = lltype.GcStruct('BIG', ('z', lltype.Signed), ('s', SMALL)) - def fn(): - x = lltype.malloc(BIG) - while x.z < 10: # makes several blocks - x.z += 3 - return x.z - check(fn, [], [], 12) - -def test_union(): - UNION = lltype.Struct('UNION', ('a', lltype.Signed), ('b', lltype.Signed), - hints = {'union': True}) - BIG = lltype.GcStruct('BIG', ('u1', UNION), ('u2', UNION)) - def fn(): - x = lltype.malloc(BIG) - x.u1.a = 3 - x.u2.b = 6 - return x.u1.b * x.u2.a - check(fn, [], [], Ellipsis) - -def test_keep_all_keepalives(): - SIZE = llmemory.sizeof(lltype.Signed) - PARRAY = lltype.Ptr(lltype.FixedSizeArray(lltype.Signed, 1)) - class A: - def __init__(self): - self.addr = llmemory.raw_malloc(SIZE) - def __del__(self): - llmemory.raw_free(self.addr) - class B: - pass - def myfunc(): - b = B() - b.keep = A() - b.data = llmemory.cast_adr_to_ptr(b.keep.addr, PARRAY) - b.data[0] = 42 - ptr = b.data - # normally 'b' could go away as early as here, which would free - # the memory held by the instance of A in b.keep... - res = ptr[0] - # ...so we explicitly keep 'b' alive until here - objectmodel.keepalive_until_here(b) - return res - graph = check(myfunc, [], [], 42, - must_be_removed=False) # 'A' instance left - - # there is a getarrayitem near the end of the graph of myfunc. - # However, the memory it accesses must still be protected by the - # following keepalive, even after malloc removal - entrymap = mkentrymap(graph) - [link] = entrymap[graph.returnblock] - assert link.prevblock.operations[-1].opname == 'keepalive' + a.big = big + a.small = big.s + a.small.x = 0 + while i > 0: + a.small.x += i + i -= 1 + return a.small.x + self.check(fn7, [int], [10], 55, must_be_removed=False) + + def test_getsubstruct(self): + SMALL = lltype.Struct('SMALL', ('x', lltype.Signed)) + BIG = lltype.GcStruct('BIG', ('z', lltype.Signed), ('s', SMALL)) + + def fn(n1, n2): + b = lltype.malloc(BIG) + b.z = n1 + b.s.x = n2 + return b.z - b.s.x + + self.check(fn, [int, int], [100, 58], 42) + + def test_fixedsizearray(self): + A = lltype.FixedSizeArray(lltype.Signed, 3) + S = lltype.GcStruct('S', ('a', A)) + + def fn(n1, n2): + s = lltype.malloc(S) + a = s.a + a[0] = n1 + a[2] = n2 + return a[0]-a[2] + + self.check(fn, [int, int], [100, 42], 58) + + def test_wrapper_cannot_be_removed(self): + SMALL = lltype.OpaqueType('SMALL') + BIG = lltype.GcStruct('BIG', ('z', lltype.Signed), ('s', SMALL)) + + def g(small): + return -1 + def fn(): + b = lltype.malloc(BIG) + g(b.s) + + self.check(fn, [], [], None, must_be_removed=False) + + def test_direct_fieldptr(self): + S = lltype.GcStruct('S', ('x', lltype.Signed)) + + def fn(): + s = lltype.malloc(S) + s.x = 11 + p = lltype.direct_fieldptr(s, 'x') + return p[0] + + self.check(fn, [], [], 11) + + def test_direct_fieldptr_2(self): + T = lltype.GcStruct('T', ('z', lltype.Signed)) + S = lltype.GcStruct('S', ('t', T), + ('x', lltype.Signed), + ('y', lltype.Signed)) + def fn(): + s = lltype.malloc(S) + s.x = 10 + s.t.z = 1 + px = lltype.direct_fieldptr(s, 'x') + py = lltype.direct_fieldptr(s, 'y') + pz = lltype.direct_fieldptr(s.t, 'z') + py[0] = 31 + return px[0] + s.y + pz[0] + + self.check(fn, [], [], 42) + + def test_getarraysubstruct(self): + U = lltype.Struct('U', ('n', lltype.Signed)) + for length in [1, 2]: + S = lltype.GcStruct('S', ('a', lltype.FixedSizeArray(U, length))) + for index in range(length): + + def fn(): + s = lltype.malloc(S) + s.a[index].n = 12 + return s.a[index].n + self.check(fn, [], [], 12) + + def test_ptr_nonzero(self): + S = lltype.GcStruct('S') + def fn(): + s = lltype.malloc(S) + return bool(s) + self.check(fn, [], [], True) + + def test_substruct_not_accessed(self): + SMALL = lltype.Struct('SMALL', ('x', lltype.Signed)) + BIG = lltype.GcStruct('BIG', ('z', lltype.Signed), ('s', SMALL)) + def fn(): + x = lltype.malloc(BIG) + while x.z < 10: # makes several blocks + x.z += 3 + return x.z + self.check(fn, [], [], 12) + + def test_union(self): + UNION = lltype.Struct('UNION', ('a', lltype.Signed), ('b', lltype.Signed), + hints = {'union': True}) + BIG = lltype.GcStruct('BIG', ('u1', UNION), ('u2', UNION)) + def fn(): + x = lltype.malloc(BIG) + x.u1.a = 3 + x.u2.b = 6 + return x.u1.b * x.u2.a + self.check(fn, [], [], Ellipsis) + + def test_keep_all_keepalives(self): + SIZE = llmemory.sizeof(lltype.Signed) + PARRAY = lltype.Ptr(lltype.FixedSizeArray(lltype.Signed, 1)) + class A: + def __init__(self): + self.addr = llmemory.raw_malloc(SIZE) + def __del__(self): + llmemory.raw_free(self.addr) + class B: + pass + def myfunc(): + b = B() + b.keep = A() + b.data = llmemory.cast_adr_to_ptr(b.keep.addr, PARRAY) + b.data[0] = 42 + ptr = b.data + # normally 'b' could go away as early as here, which would free + # the memory held by the instance of A in b.keep... + res = ptr[0] + # ...so we explicitly keep 'b' alive until here + objectmodel.keepalive_until_here(b) + return res + graph = self.check(myfunc, [], [], 42, + must_be_removed=False) # 'A' instance left + + # there is a getarrayitem near the end of the graph of myfunc. + # However, the memory it accesses must still be protected by the + # following keepalive, even after malloc removal + entrymap = mkentrymap(graph) + [link] = entrymap[graph.returnblock] + assert link.prevblock.operations[-1].opname == 'keepalive' + +class TestOOTypeMallocRemoval(BaseMallocRemovalTest): + type_system = 'ootype' + MallocRemover = OOTypeMallocRemover + + def test_oononnull(self): + FOO = ootype.Instance('Foo', ootype.ROOT) + def fn(): + s = ootype.new(FOO) + return bool(s) + self.check(fn, [], [], True) From antocuni at codespeak.net Fri Dec 29 17:27:16 2006 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Fri, 29 Dec 2006 17:27:16 +0100 (CET) Subject: [pypy-svn] r36040 - pypy/dist/pypy/translator Message-ID: <20061229162716.2388210090@code0.codespeak.net> Author: antocuni Date: Fri Dec 29 17:27:15 2006 New Revision: 36040 Modified: pypy/dist/pypy/translator/driver.py Log: Use malloc removal by default when building pypy.net Modified: pypy/dist/pypy/translator/driver.py ============================================================================== --- pypy/dist/pypy/translator/driver.py (original) +++ pypy/dist/pypy/translator/driver.py Fri Dec 29 17:27:15 2006 @@ -357,6 +357,7 @@ if self.config.translation.backend == 'cli': opt['merge_if_blocks'] = True opt['inline_threshold'] = 1 + opt['mallocs'] = True backend_optimizations(self.translator, **opt) # task_backendopt_ootype = taskdef(task_backendopt_ootype, From ericvrp at codespeak.net Sat Dec 30 00:09:49 2006 From: ericvrp at codespeak.net (ericvrp at codespeak.net) Date: Sat, 30 Dec 2006 00:09:49 +0100 (CET) Subject: [pypy-svn] r36051 - in pypy/dist/pypy/jit/codegen/llvm: . test Message-ID: <20061229230949.AA0F810095@code0.codespeak.net> Author: ericvrp Date: Sat Dec 30 00:09:37 2006 New Revision: 36051 Added: pypy/dist/pypy/jit/codegen/llvm/compatibility.py (contents, props changed) Modified: pypy/dist/pypy/jit/codegen/llvm/rgenop.py pypy/dist/pypy/jit/codegen/llvm/test/test_genc_ts.py pypy/dist/pypy/jit/codegen/llvm/test/test_operation.py pypy/dist/pypy/jit/codegen/llvm/test/test_rgenop.py Log: Moved llvm 1.9/2/0 specific code into its own file. More tests now pass on with versions. 1.9 failures are mostly caused by segfaults. Need to look into this... probably a broken llvm transformation. Added: pypy/dist/pypy/jit/codegen/llvm/compatibility.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/jit/codegen/llvm/compatibility.py Sat Dec 30 00:09:37 2006 @@ -0,0 +1,20 @@ +''' +Use this file to hide differences between llvm 1.x and 2.x . +''' +from pypy.jit.codegen.llvm.llvmjit import llvm_version + + +if llvm_version() < 2.0: + icmp = scmp = ucmp = fcmp = 'set' + inttoptr = trunc = zext = bitcast = 'cast' + shr_prefix = ('', '') +else: # >= 2.0 + icmp = 'icmp ' + scmp = 'icmp s' + ucmp = 'icmp u' + fcmp = 'fcmp o' + inttoptr = 'inttoptr' + trunc = 'trunc' + zext = 'zext' + bitcast = 'bitcast' + shr_prefix = ('l', 'a') Modified: pypy/dist/pypy/jit/codegen/llvm/rgenop.py ============================================================================== --- pypy/dist/pypy/jit/codegen/llvm/rgenop.py (original) +++ pypy/dist/pypy/jit/codegen/llvm/rgenop.py Sat Dec 30 00:09:37 2006 @@ -7,29 +7,16 @@ from pypy.rlib.objectmodel import we_are_translated from pypy.jit.codegen.i386.rgenop import gc_malloc_fnaddr from pypy.jit.codegen.llvm.conftest import option +from pypy.jit.codegen.llvm.compatibility import icmp, scmp, ucmp, fcmp, inttoptr,\ + trunc, zext, bitcast, shr_prefix -#note: To use this code you'll need llvm 2.0 . At the time of writing that -# version is still somewhere in the future so use cvs head that gets -# closest! Version 2.0 introduces fileformat changes as described here: -# http://nondot.org/sabre/LLVMNotes/TypeSystemChanges.txt - LINENO = option.lineno PRINT_SOURCE = option.print_source PRINT_DEBUG = option.print_debug WORD = 4 -llvm2 = llvmjit.llvm_version() >= 2.0 - -if llvm2: - icmp = 'icmp ' - scmp = 'icmp s' - ucmp = 'icmp u' - fcmp = 'fcmp o' -else: - icmp = scmp = ucmp = fcmp = 'set' - class ParseException(Exception): pass @@ -399,7 +386,8 @@ def op_int_lshift(self, gv_x, gv_y): gv_y_ubyte = Var('ubyte') - self.asm.append(' %s=trunc %s to ubyte' % (gv_y_ubyte.operand2(), gv_y.operand())) + self.asm.append(' %s=%s %s to ubyte' % ( + gv_y_ubyte.operand2(), trunc, gv_y.operand())) gv_result = Var(gv_x.type) self.asm.append(' %s=shl %s,%s' % ( gv_result.operand2(), gv_x.operand(), gv_y_ubyte.operand())) @@ -407,10 +395,11 @@ def op_int_rshift(self, gv_x, gv_y): gv_y_ubyte = Var('ubyte') - self.asm.append(' %s=trunc %s to ubyte' % (gv_y_ubyte.operand2(), gv_y.operand())) + self.asm.append(' %s=%s %s to ubyte' % ( + gv_y_ubyte.operand2(), trunc, gv_y.operand())) gv_result = Var(gv_x.type) self.asm.append(' %s=%sshr %s,%s' % ( - gv_result.operand2(), 'la'[gv_x.signed], gv_x.operand(), gv_y_ubyte.operand())) + gv_result.operand2(), shr_prefix[gv_x.signed], gv_x.operand(), gv_y_ubyte.operand())) return gv_result op_uint_add = op_float_add = op_int_add @@ -523,8 +512,8 @@ def genop_same_as(self, kind, gv_x): if gv_x.is_const: # must always return a var gv_result = Var(gv_x.type) - self.asm.append(' %s=bitcast %s to %s' % ( - gv_result.operand2(), gv_x.operand(), gv_x.type)) + self.asm.append(' %s=%s %s to %s' % ( + gv_result.operand2(), bitcast, gv_x.operand(), gv_x.type)) return gv_result else: return gv_x @@ -534,8 +523,8 @@ if restype is gv_x.type: return self.genop_same_as(None, gv_x) gv_result = Var(restype) - self.asm.append(' %s=zext %s to %s' % ( - gv_result.operand2(), gv_x.operand(), restype)) + self.asm.append(' %s=%s %s to %s' % ( + gv_result.operand2(), zext, gv_x.operand(), restype)) return gv_result def _trunc_to(self, gv_x, restype=None): @@ -543,8 +532,8 @@ if restype is gv_x.type: return self.genop_same_as(None, gv_x) gv_result = Var(restype) - self.asm.append(' %s=trunc %s to %s' % ( - gv_result.operand2(), gv_x.operand(), restype)) + self.asm.append(' %s=%s %s to %s' % ( + gv_result.operand2(), trunc, gv_x.operand(), restype)) return gv_result def _cast_to_bool(self, gv_x): return self._cast_to(gv_x, 'bool') @@ -776,8 +765,8 @@ if gv.is_const: gv_var = Var(gv.type) #XXX provide correct cast here - self.asm.append(' %s=inttoptr int %s to %s' % ( - gv_var.operand2(), gv.operand2(), gv_var.type)) + self.asm.append(' %s=%s int %s to %s' % ( + gv_var.operand2(), inttoptr, gv.operand2(), gv_var.type)) return gv_var return gv @@ -807,8 +796,8 @@ gv_result = Var('ubyte*') #XXX or opaque* ??? gv_gc_malloc_fnaddr = Var('%s (int)*' % gv_result.type) #XXX or use addGlobalFunctionMapping in libllvmjit.restart() - self.asm.append(' %s=inttoptr int %d to %s ;gc_malloc_fnaddr' % ( - gv_gc_malloc_fnaddr.operand2(), gc_malloc_fnaddr(), gv_gc_malloc_fnaddr.type)) + self.asm.append(' %s=%s int %d to %s ;gc_malloc_fnaddr' % ( + gv_gc_malloc_fnaddr.operand2(), inttoptr, gc_malloc_fnaddr(), gv_gc_malloc_fnaddr.type)) self.asm.append(' %s=call %s(int %d)' % ( gv_result.operand2(), gv_gc_malloc_fnaddr.operand(), size)) return gv_result @@ -819,8 +808,8 @@ gv_result = Var('ubyte*') #XXX or opaque* ??? gv_gc_malloc_fnaddr = Var('%s (int)*' % gv_result.type) #XXX or use addGlobalFunctionMapping in libllvmjit.restart() - self.asm.append(' %s=inttoptr int %d to %s ;gc_malloc_fnaddr' % ( - gv_gc_malloc_fnaddr.operand2(), gc_malloc_fnaddr(), gv_gc_malloc_fnaddr.type)) + self.asm.append(' %s=%s int %d to %s ;gc_malloc_fnaddr' % ( + gv_gc_malloc_fnaddr.operand2(), inttoptr, gc_malloc_fnaddr(), gv_gc_malloc_fnaddr.type)) self.asm.append(' %s=call %s(%s)' % ( gv_result.operand2(), gv_gc_malloc_fnaddr.operand(), gv_size.operand())) #XXX TODO set length field @@ -836,8 +825,8 @@ gv_returnvar = Var(restype) if isinstance(gv_fnptr, AddrConst): gv_fn = Var(self._funcsig_type(args_gv, restype)) - self.asm.append(' %s=bitcast %s to %s' % ( - gv_fnptr.operand2(), gv_fnptr.operand(), gv_fn.type)) + self.asm.append(' %s=%s %s to %s' % ( + gv_fnptr.operand2(), bitcast, gv_fnptr.operand(), gv_fn.type)) funcsig = gv_fn.operand() else: #XXX we probably need to call an address directly if we can't resolve the funcsig 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 Sat Dec 30 00:09:37 2006 @@ -26,17 +26,9 @@ py.test.skip('found llvm %.1f, requires at least llvm %.1f(cvs)' % ( llvm_version(), MINIMAL_VERSION)) - if llvm_version() < MINIMAL_VERSION: - test_loop_merging = skip_too_minimal - test_two_loops_merging = skip_too_minimal - test_merge_3_redconsts_before_return = skip_too_minimal - test_degenerated_before_return = skip_too_minimal - test_degenerated_before_return_2 = skip_too_minimal - test_setarrayitem = skip_too_minimal - test_degenerated_via_substructure = skip_too_minimal - test_merge_structures = skip_too_minimal - test_split_on_green_return = skip_too_minimal - test_normalize_indirect_call_more = skip_too_minimal + if llvm_version() < 2.0: + test_loop_merging = skip_too_minimal #segfault + test_two_loops_merging = skip_too_minimal #segfault if skip_passing: test_very_simple = skip @@ -93,3 +85,5 @@ test_residual_red_call = skip test_residual_red_call_with_exc = skip + test_green_char_at_merge = skip #->SomeObject() (CharRepr @rgenop.py:141 ?) + Modified: pypy/dist/pypy/jit/codegen/llvm/test/test_operation.py ============================================================================== --- pypy/dist/pypy/jit/codegen/llvm/test/test_operation.py (original) +++ pypy/dist/pypy/jit/codegen/llvm/test/test_operation.py Sat Dec 30 00:09:37 2006 @@ -23,14 +23,7 @@ llvm_version(), MINIMAL_VERSION)) if llvm_version() < 2.0: - test_arithmetic = skip_too_minimal - test_comparison = skip_too_minimal - test_char_comparison = skip_too_minimal - test_unichar_comparison = skip_too_minimal - test_char_array = skip_too_minimal - test_char_varsize_array = skip_too_minimal - test_unsigned = skip_too_minimal - test_float_arithmetic = skip_too_minimal + test_float_arithmetic = skip_too_minimal #segfault test_float_pow = skip test_unichar_array = skip Modified: pypy/dist/pypy/jit/codegen/llvm/test/test_rgenop.py ============================================================================== --- pypy/dist/pypy/jit/codegen/llvm/test/test_rgenop.py (original) +++ pypy/dist/pypy/jit/codegen/llvm/test/test_rgenop.py Sat Dec 30 00:09:37 2006 @@ -19,9 +19,9 @@ py.test.skip('found llvm %.1f, requires at least llvm %.1f(cvs)' % ( llvm_version(), MINIMAL_VERSION)) - if llvm_version() < MINIMAL_VERSION: - test_goto_direct = skip_too_minimal - test_goto_compile = skip_too_minimal - test_fact_direct = skip_too_minimal + if llvm_version() < 2.0: + test_goto_direct = skip_too_minimal #segfault + test_goto_compile = skip_too_minimal #segfault + test_fact_direct = skip_too_minimal #segfault test_fact_compile = skip #XXX Blocked block, introducted by this checkin (I don't understand) From arigo at codespeak.net Sat Dec 30 09:35:41 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 30 Dec 2006 09:35:41 +0100 (CET) Subject: [pypy-svn] r36054 - in pypy/dist/pypy/rpython/lltypesystem: . test Message-ID: <20061230083541.F085510082@code0.codespeak.net> Author: arigo Date: Sat Dec 30 09:35:40 2006 New Revision: 36054 Modified: pypy/dist/pypy/rpython/lltypesystem/lltype.py pypy/dist/pypy/rpython/lltypesystem/test/test_llmemory.py Log: Found the cause for the 'FixedSizeArray' vs 'FixedSizeArray of FixedSizeArray' bug with rctypes (try test_rpointer). Modified: pypy/dist/pypy/rpython/lltypesystem/lltype.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/lltype.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/lltype.py Sat Dec 30 09:35:40 2006 @@ -413,6 +413,10 @@ self.OF._short_name(),) _short_name = saferecursive(_short_name, '...') + def _first_struct(self): + # don't consider item0 as an inlined first substructure + return None, None + class FuncType(ContainerType): _gckind = 'raw' Modified: pypy/dist/pypy/rpython/lltypesystem/test/test_llmemory.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/test/test_llmemory.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/test/test_llmemory.py Sat Dec 30 09:35:40 2006 @@ -73,6 +73,26 @@ res = interpret(f, [0]) assert not res +def test_confusion_with_fixedarray_item_0(): + A = lltype.FixedSizeArray(lltype.Signed, 5) + B = lltype.FixedSizeArray(A, 3) + myoffset = itemoffsetof(A, 4) + global_b = lltype.malloc(B, immortal=True) + global_b[0][4] = 1000 + global_b[1][4] = 1010 + global_b[2][4] = 1200 + def f(n): + a = global_b[n] # bug: with n=0, this was considered as the + # first inlined substructure, confusing + # normalizeptr(a) into returning global_b + adr_a = cast_ptr_to_adr(a) + return (adr_a + myoffset).signed[0] + assert f(2) == 1200 + assert f(1) == 1010 + assert f(0) == 1000 + res = interpret(f, [0]) + assert res == 1000 + def test_cast_adr_to_ptr(): from pypy.rpython.memory.test.test_llinterpsim import interpret S = lltype.GcStruct("S", ("x", lltype.Signed)) From arigo at codespeak.net Sat Dec 30 11:41:14 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 30 Dec 2006 11:41:14 +0100 (CET) Subject: [pypy-svn] r36055 - in pypy/dist/pypy: rpython/lltypesystem rpython/lltypesystem/test translator/c/test Message-ID: <20061230104114.EEAB410083@code0.codespeak.net> Author: arigo Date: Sat Dec 30 11:41:11 2006 New Revision: 36055 Modified: pypy/dist/pypy/rpython/lltypesystem/llmemory.py pypy/dist/pypy/rpython/lltypesystem/test/test_llmemory.py pypy/dist/pypy/translator/c/test/test_lltyped.py Log: An extension of "addr + offset" for the case where "addr" is the address of a atructure that is actually inlined into a larger array - in which case we can add an offset to access the sibling structures of the same larger array. Modified: pypy/dist/pypy/rpython/lltypesystem/llmemory.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/llmemory.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/llmemory.py Sat Dec 30 11:41:11 2006 @@ -47,6 +47,14 @@ return ItemOffset(self.TYPE, -self.repeat) def ref(self, firstitemref): + if isinstance(firstitemref, _obref): + parent, index = lltype.parentlink(firstitemref.ob._obj) + if parent is None: + raise TypeError("address + itemoffset: not the address" + " of an array") + A = lltype.typeOf(parent) + assert isinstance(A, (lltype.Array, lltype.FixedSizeArray)) + firstitemref = _arrayitemref(parent._as_ptr(), index) assert isinstance(firstitemref, _arrayitemref) array = firstitemref.array assert lltype.typeOf(array).TO.OF == self.TYPE Modified: pypy/dist/pypy/rpython/lltypesystem/test/test_llmemory.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/test/test_llmemory.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/test/test_llmemory.py Sat Dec 30 11:41:11 2006 @@ -93,6 +93,16 @@ res = interpret(f, [0]) assert res == 1000 +def test_structarray_add(): + S = lltype.Struct("S", ("x", lltype.Signed)) + A = lltype.GcArray(S) + a = lltype.malloc(A, 5) + a[3].x = 42 + adr_s = cast_ptr_to_adr(a[0]) + adr_s += sizeof(S) * 3 + s = cast_adr_to_ptr(adr_s, lltype.Ptr(S)) + assert s.x == 42 + def test_cast_adr_to_ptr(): from pypy.rpython.memory.test.test_llinterpsim import interpret S = lltype.GcStruct("S", ("x", lltype.Signed)) Modified: pypy/dist/pypy/translator/c/test/test_lltyped.py ============================================================================== --- pypy/dist/pypy/translator/c/test/test_lltyped.py (original) +++ pypy/dist/pypy/translator/c/test/test_lltyped.py Sat Dec 30 11:41:11 2006 @@ -160,6 +160,23 @@ res = fn(4) assert res == 0 + 10 + 30 + 1000 + def test_structarray_add(self): + from pypy.rpython.lltypesystem import llmemory + S = Struct("S", ("x", Signed)) + PS = Ptr(S) + size = llmemory.sizeof(S) + A = GcArray(S) + def llf(n): + a = malloc(A, 5) + a[3].x = 42 + adr_s = llmemory.cast_ptr_to_adr(a[0]) + adr_s += size * n + s = llmemory.cast_adr_to_ptr(adr_s, PS) + return s.x + fn = self.getcompiled(llf, [int]) + res = fn(3) + assert res == 42 + def test_direct_fieldptr(self): S = GcStruct('S', ('x', Signed), ('y', Signed)) def llf(n): From arigo at codespeak.net Sat Dec 30 11:44:06 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 30 Dec 2006 11:44:06 +0100 (CET) Subject: [pypy-svn] r36056 - in pypy/dist/pypy/rpython/lltypesystem: . test Message-ID: <20061230104406.2921110076@code0.codespeak.net> Author: arigo Date: Sat Dec 30 11:44:04 2006 New Revision: 36056 Modified: pypy/dist/pypy/rpython/lltypesystem/llmemory.py pypy/dist/pypy/rpython/lltypesystem/test/test_llmemory.py Log: Fix previous check-in for FixedSizeArray instead of Array. Modified: pypy/dist/pypy/rpython/lltypesystem/llmemory.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/llmemory.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/llmemory.py Sat Dec 30 11:44:04 2006 @@ -54,6 +54,9 @@ " of an array") A = lltype.typeOf(parent) assert isinstance(A, (lltype.Array, lltype.FixedSizeArray)) + if isinstance(index, str): + assert index.startswith("item") + index = int(index[4:]) # "itemN" => N firstitemref = _arrayitemref(parent._as_ptr(), index) assert isinstance(firstitemref, _arrayitemref) array = firstitemref.array Modified: pypy/dist/pypy/rpython/lltypesystem/test/test_llmemory.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/test/test_llmemory.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/test/test_llmemory.py Sat Dec 30 11:44:04 2006 @@ -95,13 +95,13 @@ def test_structarray_add(): S = lltype.Struct("S", ("x", lltype.Signed)) - A = lltype.GcArray(S) - a = lltype.malloc(A, 5) - a[3].x = 42 - adr_s = cast_ptr_to_adr(a[0]) - adr_s += sizeof(S) * 3 - s = cast_adr_to_ptr(adr_s, lltype.Ptr(S)) - assert s.x == 42 + for a in [lltype.malloc(lltype.GcArray(S), 5), + lltype.malloc(lltype.FixedSizeArray(S, 5), immortal=True)]: + a[3].x = 42 + adr_s = cast_ptr_to_adr(a[0]) + adr_s += sizeof(S) * 3 + s = cast_adr_to_ptr(adr_s, lltype.Ptr(S)) + assert s.x == 42 def test_cast_adr_to_ptr(): from pypy.rpython.memory.test.test_llinterpsim import interpret From arigo at codespeak.net Sat Dec 30 11:46:15 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 30 Dec 2006 11:46:15 +0100 (CET) Subject: [pypy-svn] r36057 - in pypy/dist/pypy/rlib/rctypes: . test Message-ID: <20061230104615.683BC10076@code0.codespeak.net> Author: arigo Date: Sat Dec 30 11:46:12 2006 New Revision: 36057 Modified: pypy/dist/pypy/rlib/rctypes/rctypesobject.py pypy/dist/pypy/rlib/rctypes/test/test_rctypesobject.py Log: Fix pointer indexing for pointers to structures. Add a direct way to support pointer indexing: get_contents_at_index(). Some more tests. Modified: pypy/dist/pypy/rlib/rctypes/rctypesobject.py ============================================================================== --- pypy/dist/pypy/rlib/rctypes/rctypesobject.py (original) +++ pypy/dist/pypy/rlib/rctypes/rctypesobject.py Sat Dec 30 11:46:12 2006 @@ -249,6 +249,15 @@ targetmemblock = self._getmemblock(0, targetkeepalives) return contentscls(targetaddr, targetmemblock) + def get_contents_at_index(self, index): + ptr = self.ll_ref(RCTypesPtr.CDATATYPE) + targetaddr = llmemory.cast_ptr_to_adr(ptr[0]) + targetaddr += ofs_item * index + keepalive_until_here(self) + targetkeepalives = contentscls.num_keepalives + targetmemblock = self._getmemblock(0, targetkeepalives) + return contentscls(targetaddr, targetmemblock) + def set_contents(self, newcontentsbox): targetaddr = newcontentsbox.addr targetmemblock = newcontentsbox.memblock @@ -258,6 +267,7 @@ keepalive_until_here(self) self._keepalivememblock(0, targetmemblock) + ofs_item = llmemory.sizeof(contentscls.LLTYPE) contentscls._ptrcls = RCTypesPtr return RCTypesPtr RPointer._annspecialcase_ = 'specialize:memo' Modified: pypy/dist/pypy/rlib/rctypes/test/test_rctypesobject.py ============================================================================== --- pypy/dist/pypy/rlib/rctypes/test/test_rctypesobject.py (original) +++ pypy/dist/pypy/rlib/rctypes/test/test_rctypesobject.py Sat Dec 30 11:46:12 2006 @@ -66,6 +66,18 @@ res = self.do(func) assert res == 303 + def test_copyfrom_2(self): + def func(): + x1 = rc_int.allocate() + x1.set_value(11) + x2 = rc_int.allocate() + x2.set_value(7) + p1 = pointer(x1) + p1.get_contents().copyfrom(x2) + return x1.get_value() + res = self.do(func) + assert res == 7 + def test_fixedarray(self): def func(): a = RFixedArray(rc_int, 10).allocate() @@ -99,11 +111,27 @@ a1 = RVarArray(rc_int).fromitem(p.get_contents(), 8) del p for i in range(8): - a1.ref(i).get_value() == 100 + 5 * i + assert a1.ref(i).get_value() == 100 + 5 * i return a1.length res = self.do(func) assert res == 8 + def test_varstructarray_cast(self): + S1 = RStruct('S1', [('x', rc_int), + ('y', rc_int)]) + def func(): + a = RVarArray(S1).allocate(10) + for i in range(10): + a.ref(i).ref_x().set_value(100 + 5 * i) + a.ref(i).ref_y().set_value(200 + 2 * i) + p = pointer(a.ref(0)) + del a + a1 = RVarArray(S1).fromitem(p.get_contents(), 8) + del p + return a1.ref(4).ref_y().get_value() + res = self.do(func) + assert res == 208 + def test_char_p(self): def func(): p = rc_char_p.allocate() @@ -186,6 +214,31 @@ res = self.do(func) assert res == 7 + def test_pointer_indexing(self): + def func(): + a = RFixedArray(rc_int, 10).allocate() + for i in range(10): + a.ref(i).set_value(100 + 5 * i) + p = pointer(a.ref(0)) + del a + return p.get_contents_at_index(7).get_value() + res = self.do(func) + assert res == 135 + + def test_structpointer_indexing(self): + S1 = RStruct('S1', [('x', rc_int), + ('y', rc_int)]) + def func(): + a = RFixedArray(S1, 10).allocate() + for i in range(10): + a.ref(i).ref_x().set_value(100 + 5 * i) + a.ref(i).ref_y().set_value(200 + 2 * i) + p = pointer(a.ref(0)) + del a + s1 = p.get_contents_at_index(3) + return s1.ref_x().get_value() + s1.ref_y().get_value() + res = self.do(func) + assert res == 115 + 206 POLICY = AnnotatorPolicy() POLICY.allow_someobjects = False From guido at codespeak.net Sat Dec 30 14:29:14 2006 From: guido at codespeak.net (guido at codespeak.net) Date: Sat, 30 Dec 2006 14:29:14 +0100 (CET) Subject: [pypy-svn] r36059 - in pypy/dist/pypy/tool/build: . bin test Message-ID: <20061230132914.CDA1C10077@code0.codespeak.net> Author: guido Date: Sat Dec 30 14:29:10 2006 New Revision: 36059 Modified: pypy/dist/pypy/tool/build/bin/server pypy/dist/pypy/tool/build/config.py pypy/dist/pypy/tool/build/server.py pypy/dist/pypy/tool/build/test/fake.py pypy/dist/pypy/tool/build/test/test_build.py pypy/dist/pypy/tool/build/test/test_pypybuilder.py pypy/dist/pypy/tool/build/test/test_server.py Log: Errors are now reported to the client properly, errors in mail sending are caught, config is passed around as an object rather than different values (makes the code a bit cleaner), sending urls rather than paths to the client. Modified: pypy/dist/pypy/tool/build/bin/server ============================================================================== --- pypy/dist/pypy/tool/build/bin/server (original) +++ pypy/dist/pypy/tool/build/bin/server Sat Dec 30 14:29:10 2006 @@ -3,8 +3,6 @@ import path from pypy.tool.build import config -from py.execnet import SshGateway - if __name__ == '__main__': from py.execnet import SshGateway, PopenGateway from pypy.tool.build.server import init @@ -13,18 +11,11 @@ gw = PopenGateway() else: gw = SshGateway(config.server) - channel = init(gw, port=config.port, path=config.path, - projectname=config.projectname, - buildpath=str(config.buildpath), - mailhost=config.mailhost, - mailport=config.mailport, - mailfrom=config.mailfrom) + channel = init(gw, config) try: while 1: data = channel.receive() - if not isinstance(data, str): - print 'received non-string "%s", ignoring' % (repr(data)[:10],) print data finally: channel.close() Modified: pypy/dist/pypy/tool/build/config.py ============================================================================== --- pypy/dist/pypy/tool/build/config.py (original) +++ pypy/dist/pypy/tool/build/config.py Sat Dec 30 14:29:10 2006 @@ -53,3 +53,8 @@ root = root[:-1] return '%s/%s' % (root, p) +# create an URL from a path, the URL is used in emails +def path_to_url(p): + return 'http://codespeak.net/pypy/%s' % ( + p.relto(py.magic.autopath().dirpath()),) + Modified: pypy/dist/pypy/tool/build/server.py ============================================================================== --- pypy/dist/pypy/tool/build/server.py (original) +++ pypy/dist/pypy/tool/build/server.py Sat Dec 30 14:29:10 2006 @@ -33,19 +33,15 @@ """ retry_interval = 10 - def __init__(self, projname, channel, builddir, mailhost=None, - mailport=None, mailfrom=None): - self._projname = projname + def __init__(self, config, channel): + self.config = config self._channel = channel - self._buildroot = py.path.local(builddir) - self._mailhost = mailhost - self._mailport = mailport - self._mailfrom = mailfrom + self._buildroot = buildpath = py.path.local(config.buildpath) self._clients = [] done = [] - for bp in self._get_buildpaths(builddir): + for bp in self._get_buildpaths(buildpath): if bp.done: done.append(bp) else: @@ -217,7 +213,7 @@ self._queuelock.release() def _get_buildpaths(self, dirpath): - for p in py.path.local(dirpath).listdir(): + for p in dirpath.listdir(): yield BuildPath(str(p)) _i = 0 @@ -228,7 +224,7 @@ buildnames = [p.basename for p in py.path.local(self._buildroot).listdir()] while True: - name = '%s-%s-%s' % (self._projname, today, self._i) + name = '%s-%s-%s' % (self.config.projectname, today, self._i) self._i += 1 if name not in buildnames: return name @@ -237,21 +233,39 @@ def _send_email(self, addr, buildpath): self._channel.send('going to send email to %s' % (addr,)) - if self._mailhost is not None: - msg = '\r\n'.join([ - 'From: %s' % (self._mailfrom,), - 'To: %s' % (addr,), - 'Subject: %s compilation done' % (self._projname,), - '', - 'The compilation you requested is done. You can find it at', - str(build.path), - '', - buildpath.log, - ]) - server = smtplib.SMTP(self._mailhost, self._mailport) - server.set_debuglevel(0) - server.sendmail(self._mailfrom, addr, msg) - server.quit() + if self.config.mailhost is not None: + try: + if buildpath.error: + subject = '%s - %s during compilation' % ( + self.config.projectname, + buildpath.error.__class__.__name__) + body = ('There was an error during the compilation you ' + 'requested. The log can be found below.') + else: + subject = '%s - compilation done' % ( + self.config.projectname,) + body = ('The compilation you requested is done. You can ' + 'find it at:\n%s\n' % ( + self.config.path_to_url(buildpath,))) + msg = '\r\n'.join([ + 'From: %s' % (self.config.mailfrom,), + 'To: %s' % (addr,), + 'Subject: %s' % (subject,), + '', + body, + '', + buildpath.log, + ]) + server = smtplib.SMTP(self.config.mailhost, + self.config.mailport) + server.set_debuglevel(0) + server.sendmail(self.config.mailfrom, addr, msg) + server.quit() + except: + exc, e, tb = py.std.sys.exc_info() + self._channel.send( + 'exception sending mail: %s - %s' % (exc, e)) + del tb initcode = """ import sys @@ -260,7 +274,8 @@ try: try: from pypy.tool.build.server import PPBServer - server = PPBServer(%r, channel, %r, %r, %r, %r) + from pypy.tool.build import config + server = PPBServer(config, channel) # make the server available to clients as pypy.tool.build.ppbserver from pypy.tool import build @@ -283,12 +298,10 @@ finally: channel.close() """ -def init(gw, port=12321, path=[], projectname='pypy', buildpath=None, - mailhost=None, mailport=25, mailfrom=None): +def init(gw, config): from pypy.tool.build import execnetconference - conference = execnetconference.conference(gw, port, True) - channel = conference.remote_exec(initcode % (path, projectname, buildpath, - mailhost, mailport, - mailfrom)) + + conference = execnetconference.conference(gw, config.port, True) + channel = conference.remote_exec(initcode % (config.path,)) return channel Modified: pypy/dist/pypy/tool/build/test/fake.py ============================================================================== --- pypy/dist/pypy/tool/build/test/fake.py (original) +++ pypy/dist/pypy/tool/build/test/fake.py Sat Dec 30 14:29:10 2006 @@ -52,3 +52,7 @@ bp.ensure(dir=1) return bp +class Container(object): + def __init__(self, **kwargs): + self.__dict__.update(kwargs) + Modified: pypy/dist/pypy/tool/build/test/test_build.py ============================================================================== --- pypy/dist/pypy/tool/build/test/test_build.py (original) +++ pypy/dist/pypy/tool/build/test/test_build.py Sat Dec 30 14:29:10 2006 @@ -153,6 +153,7 @@ def test_buildrequest_error(): tempdir = py.test.ensuretemp('pypybuilder-buildpath') + bp = build.BuildPath(str(tempdir / 'test_error')) assert bp.error is None bp.log = """ @@ -167,6 +168,7 @@ e = bp.error assert e.__class__ == SyntaxError assert str(e) == 'foo' + bp.log = """ ============================================================================== Exception during compilation: Modified: pypy/dist/pypy/tool/build/test/test_pypybuilder.py ============================================================================== --- pypy/dist/pypy/tool/build/test/test_pypybuilder.py (original) +++ pypy/dist/pypy/tool/build/test/test_pypybuilder.py Sat Dec 30 14:29:10 2006 @@ -1,3 +1,7 @@ +""" some functional tests (although some of the rest aren't strictly + unit tests either), to run use --functional as an arg to py.test +""" + import py import time import path @@ -9,10 +13,7 @@ from pypy.config import config as pypyconfig from repo import create_temp_repo - -""" some functional tests (although some of the rest aren't strictly - unit tests either), to run use --functional as an arg to py.test -""" +from fake import Container # XXX this one is a bit messy, it's a quick functional test for the whole # system, but for instance contains time.sleep()s to make sure all threads @@ -38,11 +39,15 @@ mod.foourl = str(repo.join('foo')) config.checkers = [] - mod.sgw = sgw = py.execnet.PopenGateway() mod.temppath = temppath = py.test.ensuretemp('pypybuilder-functional') - mod.sc = sc = server.init(sgw, port=config.testport, path=config.testpath, - buildpath=str(temppath)) + mod.sgw = sgw = py.execnet.PopenGateway() + cfg = Container(projectname='pypytest', server='localhost', + port=config.testport, + path=config.testpath, buildpath=temppath, + mailhost=None) + + mod.sc = sc = server.init(sgw, cfg) def read(): while 1: @@ -64,7 +69,7 @@ sysconfig = _get_sysconfig() sysconfig.__dict__.update(conf) channel = client.init(cgw, sysconfig, port=config.testport, - testing_sleeptime=SLEEP_INTERVAL * 4) + testing_sleeptime=SLEEP_INTERVAL * 5) channel.send(True) return cgw, channel @@ -161,7 +166,7 @@ # this sleep, along with that in the previous compile call, should be # enough to reach the end of fake compilation - time.sleep(SLEEP_INTERVAL * 3) + time.sleep(SLEEP_INTERVAL * 4) # both the jobs should have been done now... queued = get_info('_queued') Modified: pypy/dist/pypy/tool/build/test/test_server.py ============================================================================== --- pypy/dist/pypy/tool/build/test/test_server.py (original) +++ pypy/dist/pypy/tool/build/test/test_server.py Sat Dec 30 14:29:10 2006 @@ -1,14 +1,16 @@ import path from pypy.tool.build import server import py -from fake import FakeChannel, FakeClient +from fake import FakeChannel, FakeClient, Container from pypy.tool.build import build import time from repo import create_temp_repo def setup_module(mod): mod.temppath = temppath = py.test.ensuretemp('pypybuilder-server') - mod.svr = server.PPBServer('pypytest', FakeChannel(), str(temppath)) + config = Container(projectname='pypytest', buildpath=temppath, + mailhost=None) + mod.svr = server.PPBServer(config, FakeChannel()) mod.c1 = FakeClient({'foo': 1, 'bar': [1,2]}) mod.svr.register(mod.c1) @@ -148,7 +150,8 @@ bp2 = build.BuildPath(temppath.join('bp2')) bp2.ensure(dir=True) bp2.log = 'log' - svr = server.PPBServer('test', FakeChannel(), str(temppath)) + config = Container(projectname='test', buildpath=temppath) + svr = server.PPBServer(config, FakeChannel()) assert not bp1.check() assert bp2.check() From arigo at codespeak.net Sat Dec 30 17:20:49 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 30 Dec 2006 17:20:49 +0100 (CET) Subject: [pypy-svn] r36061 - pypy/dist/pypy/doc Message-ID: <20061230162049.F3B9010077@code0.codespeak.net> Author: arigo Date: Sat Dec 30 17:20:48 2006 New Revision: 36061 Modified: pypy/dist/pypy/doc/index.txt Log: A direct link to jit.txt, which is not complete but complete enough to be interesting IMHO. Modified: pypy/dist/pypy/doc/index.txt ============================================================================== --- pypy/dist/pypy/doc/index.txt (original) +++ pypy/dist/pypy/doc/index.txt Sat Dec 30 17:20:48 2006 @@ -83,6 +83,9 @@ `JavaScript backend`_ describes how to use the JavaScript backend to create AJAX-based web pages. +`JIT Generation in PyPy`_ describes how we produce the Python Just-in-time Compiler +from our Python interpreter. + `EU reports`_ is a page that contains links to the preliminary reports that we submitted to the European Union. @@ -315,6 +318,7 @@ .. _`extension compiler`: extcompiler.html .. _`py.py`: getting-started.html#main-entry-point .. _`translatorshell.py`: getting-started.html#try-out-the-translator +.. _`JIT Generation in PyPy`: jit.html .. _`just-in-time compiler generator`: jit.html .. _`jit backends`: jit.html#backends .. _`hint-annotator`: jit.html#hint-annotator From arigo at codespeak.net Sat Dec 30 18:24:13 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 30 Dec 2006 18:24:13 +0100 (CET) Subject: [pypy-svn] r36065 - pypy/dist/pypy/jit/codegen/i386/test Message-ID: <20061230172413.1BBCC1007A@code0.codespeak.net> Author: arigo Date: Sat Dec 30 18:24:12 2006 New Revision: 36065 Modified: pypy/dist/pypy/jit/codegen/i386/test/test_interp_ts.py Log: These tests take ages and are not really useful. Modified: pypy/dist/pypy/jit/codegen/i386/test/test_interp_ts.py ============================================================================== --- pypy/dist/pypy/jit/codegen/i386/test/test_interp_ts.py (original) +++ pypy/dist/pypy/jit/codegen/i386/test/test_interp_ts.py Sat Dec 30 18:24:12 2006 @@ -1,4 +1,5 @@ -import os +import os, py +py.test.skip("these tests take ages and are not really useful") from pypy.annotation import model as annmodel from pypy.jit.timeshifter.test import test_timeshift from pypy.jit.codegen.i386.rgenop import RI386GenOp, IntConst From pedronis at codespeak.net Sun Dec 31 02:12:00 2006 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Sun, 31 Dec 2006 02:12:00 +0100 (CET) Subject: [pypy-svn] r36068 - in pypy/dist/pypy/translator/backendopt: . test Message-ID: <20061231011200.2CD741007F@code0.codespeak.net> Author: pedronis Date: Sun Dec 31 02:11:54 2006 New Revision: 36068 Modified: pypy/dist/pypy/translator/backendopt/all.py pypy/dist/pypy/translator/backendopt/malloc.py pypy/dist/pypy/translator/backendopt/test/test_malloc.py Log: umph, reverting the ootype malloc removal refactoring 36037 (and consequently 36040), it needs more careful review. It broke in a shallow way backendopt/test/test_all.py but once the shallow breakage is repaired we see that a bunch of tests there are failing because malloc removal is not happening anymore it seems. This needs to be fixed in such way that test_all and translator/test/test_simplify pass again and then it can be checked in again. test_all is quite an important test for *all* backendopts! Modified: pypy/dist/pypy/translator/backendopt/all.py ============================================================================== --- pypy/dist/pypy/translator/backendopt/all.py (original) +++ pypy/dist/pypy/translator/backendopt/all.py Sun Dec 31 02:11:54 2006 @@ -92,7 +92,6 @@ def inline_malloc_removal_phase(config, translator, graphs, inline_threshold, call_count_pred=None): - type_system = translator.rtyper.type_system.name log.inlining("phase with threshold factor: %s" % inline_threshold) # inline functions in each other @@ -114,7 +113,7 @@ if config.mallocs: tot = 0 for graph in graphs: - count = remove_simple_mallocs(graph, type_system) + count = remove_simple_mallocs(graph) if count: # remove typical leftovers from malloc removal removenoops.remove_same_as(graph) Modified: pypy/dist/pypy/translator/backendopt/malloc.py ============================================================================== --- pypy/dist/pypy/translator/backendopt/malloc.py (original) +++ pypy/dist/pypy/translator/backendopt/malloc.py Sun Dec 31 02:11:54 2006 @@ -2,7 +2,6 @@ from pypy.objspace.flow.model import SpaceOperation, traverse from pypy.tool.algo.unionfind import UnionFind from pypy.rpython.lltypesystem import lltype -from pypy.rpython.ootypesystem import ootype from pypy.translator.simplify import remove_identical_vars from pypy.translator.backendopt.support import log @@ -50,58 +49,7 @@ raise NotImplementedError def flowin(self, block, count, var, newvarsmap): - # in this 'block', follow where the 'var' goes to and replace - # it by a flattened-out family of variables. This family is given - # by newvarsmap, whose keys are the 'flatnames'. - vars = {var: True} - self.last_removed_access = None - - def list_newvars(): - return [newvarsmap[key] for key in self.flatnames] - - assert block.operations != () - self.newops = [] - for op in block.operations: - for arg in op.args[1:]: # should be the first arg only - assert arg not in vars - if op.args and op.args[0] in vars: - self.flowin_op(op, vars, newvarsmap) - elif op.result in vars: - assert op.opname == self.MALLOC_OP - assert vars == {var: True} - progress = True - # drop the "malloc" operation - newvarsmap = self.flatconstants.copy() # zero initial values - # if there are substructures, they are now individually - # malloc'ed in an exploded way. (They will typically be - # removed again by the next malloc removal pass.) - for key in self.needsubmallocs: - v = Variable() - v.concretetype = self.newvarstype[key] - c = Constant(v.concretetype.TO, lltype.Void) - if c.value == op.args[0].value: - progress = False # replacing a malloc with - # the same malloc! - newop = SpaceOperation(self.MALLOC_OP, [c], v) - self.newops.append(newop) - newvarsmap[key] = v - count[0] += progress - else: - self.newops.append(op) - - assert block.exitswitch not in vars - - for link in block.exits: - newargs = [] - for arg in link.args: - if arg in vars: - newargs += list_newvars() - else: - newargs.append(arg) - link.args[:] = newargs - - self.insert_keepalives(list_newvars()) - block.operations[:] = self.newops + raise NotImplementedError def compute_lifetimes(self, graph): """Compute the static data flow of the graph: returns a list of LifeTime @@ -419,170 +367,141 @@ pass return S, fldname - def flowin_op(self, op, vars, newvarsmap): - if op.opname in ("getfield", "getarrayitem"): - S = op.args[0].concretetype.TO - fldname = op.args[1].value - key = self.key_for_field_access(S, fldname) - if key in self.accessed_substructs: - c_name = Constant('data', lltype.Void) - newop = SpaceOperation("getfield", - [newvarsmap[key], c_name], - op.result) - else: - newop = SpaceOperation("same_as", - [newvarsmap[key]], - op.result) - self.newops.append(newop) - self.last_removed_access = len(self.newops) - elif op.opname in ("setfield", "setarrayitem"): - S = op.args[0].concretetype.TO - fldname = op.args[1].value - key = self.key_for_field_access(S, fldname) - assert key in newvarsmap - if key in self.accessed_substructs: - c_name = Constant('data', lltype.Void) - newop = SpaceOperation("setfield", - [newvarsmap[key], c_name, op.args[2]], - op.result) - self.newops.append(newop) - else: - newvarsmap[key] = op.args[2] - self.last_removed_access = len(self.newops) - elif op.opname in ("same_as", "cast_pointer"): - assert op.result not in vars - vars[op.result] = True - # Consider the two pointers (input and result) as - # equivalent. We can, and indeed must, use the same - # flattened list of variables for both, as a "setfield" - # via one pointer must be reflected in the other. - elif op.opname == 'keepalive': - self.last_removed_access = len(self.newops) - elif op.opname in ("getsubstruct", "getarraysubstruct", - "direct_fieldptr"): - S = op.args[0].concretetype.TO - fldname = op.args[1].value - if op.opname == "getarraysubstruct": - fldname = 'item%d' % fldname - equiv = self.equivalent_substruct(S, fldname) - if equiv: - # exactly like a cast_pointer - assert op.result not in vars - vars[op.result] = True + def flowin(self, block, count, var, newvarsmap): + # in this 'block', follow where the 'var' goes to and replace + # it by a flattened-out family of variables. This family is given + # by newvarsmap, whose keys are the 'flatnames'. + vars = {var: True} + last_removed_access = None + + def list_newvars(): + return [newvarsmap[key] for key in self.flatnames] + + assert block.operations != () + newops = [] + for op in block.operations: + for arg in op.args[1:]: # should be the first arg only + assert arg not in vars + if op.args and op.args[0] in vars: + if op.opname in ("getfield", "getarrayitem"): + S = op.args[0].concretetype.TO + fldname = op.args[1].value + key = self.key_for_field_access(S, fldname) + if key in self.accessed_substructs: + c_name = Constant('data', lltype.Void) + newop = SpaceOperation("getfield", + [newvarsmap[key], c_name], + op.result) + else: + newop = SpaceOperation("same_as", + [newvarsmap[key]], + op.result) + newops.append(newop) + last_removed_access = len(newops) + elif op.opname in ("setfield", "setarrayitem"): + S = op.args[0].concretetype.TO + fldname = op.args[1].value + key = self.key_for_field_access(S, fldname) + assert key in newvarsmap + if key in self.accessed_substructs: + c_name = Constant('data', lltype.Void) + newop = SpaceOperation("setfield", + [newvarsmap[key], c_name, op.args[2]], + op.result) + newops.append(newop) + else: + newvarsmap[key] = op.args[2] + last_removed_access = len(newops) + elif op.opname in ("same_as", "cast_pointer"): + assert op.result not in vars + vars[op.result] = True + # Consider the two pointers (input and result) as + # equivalent. We can, and indeed must, use the same + # flattened list of variables for both, as a "setfield" + # via one pointer must be reflected in the other. + elif op.opname == 'keepalive': + last_removed_access = len(newops) + elif op.opname in ("getsubstruct", "getarraysubstruct", + "direct_fieldptr"): + S = op.args[0].concretetype.TO + fldname = op.args[1].value + if op.opname == "getarraysubstruct": + fldname = 'item%d' % fldname + equiv = self.equivalent_substruct(S, fldname) + if equiv: + # exactly like a cast_pointer + assert op.result not in vars + vars[op.result] = True + else: + # do it with a getsubstruct on the independently + # malloc'ed GcStruct + if op.opname == "direct_fieldptr": + opname = "direct_fieldptr" + else: + opname = "getsubstruct" + v = newvarsmap[S, fldname] + cname = Constant('data', lltype.Void) + newop = SpaceOperation(opname, + [v, cname], + op.result) + newops.append(newop) + elif op.opname in ("ptr_iszero", "ptr_nonzero"): + # we know the pointer is not NULL if it comes from + # a successful malloc + c = Constant(op.opname == "ptr_nonzero", lltype.Bool) + newop = SpaceOperation('same_as', [c], op.result) + newops.append(newop) + else: + raise AssertionError, op.opname + elif op.result in vars: + assert op.opname == self.MALLOC_OP + assert vars == {var: True} + progress = True + # drop the "malloc" operation + newvarsmap = self.flatconstants.copy() # zero initial values + # if there are substructures, they are now individually + # malloc'ed in an exploded way. (They will typically be + # removed again by the next malloc removal pass.) + for key in self.needsubmallocs: + v = Variable() + v.concretetype = self.newvarstype[key] + c = Constant(v.concretetype.TO, lltype.Void) + if c.value == op.args[0].value: + progress = False # replacing a malloc with + # the same malloc! + newop = SpaceOperation(self.MALLOC_OP, [c], v) + newops.append(newop) + newvarsmap[key] = v + count[0] += progress else: - # do it with a getsubstruct on the independently - # malloc'ed GcStruct - if op.opname == "direct_fieldptr": - opname = "direct_fieldptr" + newops.append(op) + + assert block.exitswitch not in vars + + for link in block.exits: + newargs = [] + for arg in link.args: + if arg in vars: + newargs += list_newvars() else: - opname = "getsubstruct" - v = newvarsmap[S, fldname] - cname = Constant('data', lltype.Void) - newop = SpaceOperation(opname, - [v, cname], - op.result) - self.newops.append(newop) - elif op.opname in ("ptr_iszero", "ptr_nonzero"): - # we know the pointer is not NULL if it comes from - # a successful malloc - c = Constant(op.opname == "ptr_nonzero", lltype.Bool) - newop = SpaceOperation('same_as', [c], op.result) - self.newops.append(newop) - else: - raise AssertionError, op.opname - - - def insert_keepalives(self, newvars): - if self.last_removed_access is not None: + newargs.append(arg) + link.args[:] = newargs + + if last_removed_access is not None: keepalives = [] - for v in newvars: + for v in list_newvars(): T = v.concretetype if isinstance(T, lltype.Ptr) and T._needsgc(): v0 = Variable() v0.concretetype = lltype.Void newop = SpaceOperation('keepalive', [v], v0) keepalives.append(newop) - self.newops[self.last_removed_access:self.last_removed_access] = keepalives - -class OOTypeMallocRemover(BaseMallocRemover): - - IDENTITY_OPS = ('same_as', 'ooupcast', 'oodowncast') - SUBSTRUCT_OPS = () - MALLOC_OP = 'new' - FIELD_ACCESS = dict.fromkeys(["oogetfield", - "oosetfield", - "oononnull", - #"oois", # ??? - #"instanceof", # ??? - ]) - SUBSTRUCT_ACCESS = {} - CHECK_ARRAY_INDEX = {} - - def get_STRUCT(self, TYPE): - return TYPE - - def union_wrapper(self, S): - return False - - def RTTI_dtor(self, STRUCT): - return False + newops[last_removed_access:last_removed_access] = keepalives - def _get_fields(self, TYPE): - if isinstance(TYPE, ootype.Record): - return TYPE._fields - elif isinstance(TYPE, ootype.Instance): - return TYPE._allfields() - else: - assert False - - def flatten(self, TYPE): - for name, (FIELDTYPE, default) in self._get_fields(TYPE).iteritems(): - key = TYPE, name - example = FIELDTYPE._defl() - constant = Constant(example) - constant.concretetype = FIELDTYPE - self.flatconstants[key] = constant - self.flatnames.append(key) - self.newvarstype[key] = FIELDTYPE + block.operations[:] = newops - def key_for_field_access(self, S, fldname): - return S, fldname - - def flowin_op(self, op, vars, newvarsmap): - if op.opname == "oogetfield": - S = op.args[0].concretetype - fldname = op.args[1].value - key = self.key_for_field_access(S, fldname) - newop = SpaceOperation("same_as", - [newvarsmap[key]], - op.result) - self.newops.append(newop) - last_removed_access = len(self.newops) - elif op.opname == "oosetfield": - S = op.args[0].concretetype - fldname = op.args[1].value - key = self.key_for_field_access(S, fldname) - assert key in newvarsmap - newvarsmap[key] = op.args[2] - last_removed_access = len(self.newops) - elif op.opname in ("same_as", "oodowncast", "ooupcast"): - assert op.result not in vars - vars[op.result] = True - # Consider the two pointers (input and result) as - # equivalent. We can, and indeed must, use the same - # flattened list of variables for both, as a "setfield" - # via one pointer must be reflected in the other. - elif op.opname == "oononnull": - # we know the pointer is not NULL if it comes from - # a successful malloc - c = Constant(True, lltype.Bool) - newop = SpaceOperation('same_as', [c], op.result) - self.newops.append(newop) - else: - raise AssertionError, op.opname - - def insert_keepalives(self, newvars): - pass +class OOTypeMallocRemover(BaseMallocRemover): + pass # TODO def remove_simple_mallocs(graph, type_system='lltype'): if type_system == 'lltype': Modified: pypy/dist/pypy/translator/backendopt/test/test_malloc.py ============================================================================== --- pypy/dist/pypy/translator/backendopt/test/test_malloc.py (original) +++ pypy/dist/pypy/translator/backendopt/test/test_malloc.py Sun Dec 31 02:11:54 2006 @@ -1,5 +1,5 @@ import py -from pypy.translator.backendopt.malloc import LLTypeMallocRemover, OOTypeMallocRemover +from pypy.translator.backendopt.malloc import LLTypeMallocRemover from pypy.translator.backendopt.inline import inline_function from pypy.translator.backendopt.all import backend_optimizations from pypy.translator.translator import TranslationContext, graphof @@ -7,336 +7,311 @@ from pypy.objspace.flow.model import checkgraph, flatten, Block, mkentrymap from pypy.rpython.llinterp import LLInterpreter from pypy.rpython.lltypesystem import lltype, llmemory -from pypy.rpython.ootypesystem import ootype from pypy.rlib import objectmodel from pypy.conftest import option -class BaseMallocRemovalTest(object): - type_system = None - MallocRemover = None - - def _skip_oo(self, msg): - if self.type_system == 'ootype': - py.test.skip(msg) - - def check_malloc_removed(self, graph): - remover = self.MallocRemover() - checkgraph(graph) - count1 = count2 = 0 - for node in flatten(graph): - if isinstance(node, Block): - for op in node.operations: - if op.opname == self.MallocRemover.MALLOC_OP: - S = op.args[0].value - if not remover.union_wrapper(S): # union wrappers are fine - count1 += 1 - if op.opname in ('direct_call', 'indirect_call'): - count2 += 1 - assert count1 == 0 # number of mallocs left - assert count2 == 0 # number of calls left - - def check(self, fn, signature, args, expected_result, must_be_removed=True): - remover = self.MallocRemover() - t = TranslationContext() - t.buildannotator().build_types(fn, signature) - t.buildrtyper(type_system=self.type_system).specialize() - graph = graphof(t, fn) - if option.view: - t.view() - # to detect missing keepalives and broken intermediate graphs, - # we do the loop ourselves instead of calling remove_simple_mallocs() - while True: - progress = remover.remove_mallocs_once(graph) - simplify.transform_dead_op_vars_in_blocks(list(graph.iterblocks())) - if progress and option.view: - t.view() - if expected_result is not Ellipsis: - interp = LLInterpreter(t.rtyper) - res = interp.eval_graph(graph, args) - assert res == expected_result - if not progress: - break - if must_be_removed: - self.check_malloc_removed(graph) - return graph - - def test_fn1(self): - def fn1(x, y): - if x > 0: - t = x+y, x-y - else: - t = x-y, x+y - s, d = t - return s*d - self.check(fn1, [int, int], [15, 10], 125) - - def test_fn2(self): - class T: - pass - def fn2(x, y): - t = T() - t.x = x - t.y = y - if x > 0: - return t.x + t.y - else: - return t.x - t.y - self.check(fn2, [int, int], [-6, 7], -13) - - def test_fn3(self): - def fn3(x): - a, ((b, c), d, e) = x+1, ((x+2, x+3), x+4, x+5) - return a+b+c+d+e - self.check(fn3, [int], [10], 65) - - def test_fn4(self): - class A: - pass - class B(A): - pass - def fn4(i): - a = A() - b = B() - a.b = b - b.i = i - return a.b.i - self.check(fn4, [int], [42], 42) - - def test_fn5(self): - self._skip_oo('It will work as soon as trivial oosend are inlined') - class A: - attr = 666 - class B(A): - attr = 42 - def fn5(): - b = B() - return b.attr - self.check(fn5, [], [], 42) - - def test_aliasing(self): - class A: - pass - def fn6(n): - a1 = A() - a1.x = 5 - a2 = A() - a2.x = 6 - if n > 0: - a = a1 - else: - a = a2 - a.x = 12 - return a1.x - self.check(fn6, [int], [1], 12, must_be_removed=False) - - - -class TestLLTypeMallocRemoval(BaseMallocRemovalTest): - type_system = 'lltype' - MallocRemover = LLTypeMallocRemover - - def test_with_keepalive(self): - from pypy.rlib.objectmodel import keepalive_until_here - def fn1(x, y): - if x > 0: - t = x+y, x-y - else: - t = x-y, x+y - s, d = t - keepalive_until_here(t) - return s*d - self.check(fn1, [int, int], [15, 10], 125) - - def test_dont_remove_with__del__(self): - import os - delcalls = [0] - class A(object): - nextid = 0 - def __init__(self): - self.id = self.nextid - self.nextid += 1 - - def __del__(self): - delcalls[0] += 1 - os.write(1, "__del__\n") - def f(x=int): - a = A() - i = 0 - while i < x: - a = A() - os.write(1, str(delcalls[0]) + "\n") - i += 1 - return 1 - t = TranslationContext() - t.buildannotator().build_types(f, [int]) - t.buildrtyper().specialize() - graph = graphof(t, f) - backend_optimizations(t) - op = graph.startblock.exits[0].target.exits[1].target.operations[0] - assert op.opname == "malloc" - - def test_add_keepalives(self): - class A: - pass - SMALL = lltype.Struct('SMALL', ('x', lltype.Signed)) - BIG = lltype.GcStruct('BIG', ('z', lltype.Signed), ('s', SMALL)) - def fn7(i): - big = lltype.malloc(BIG) +def check_malloc_removed(graph): + remover = LLTypeMallocRemover() + checkgraph(graph) + count1 = count2 = 0 + for node in flatten(graph): + if isinstance(node, Block): + for op in node.operations: + if op.opname == 'malloc': + S = op.args[0].value + if not remover.union_wrapper(S): # union wrappers are fine + count1 += 1 + if op.opname in ('direct_call', 'indirect_call'): + count2 += 1 + assert count1 == 0 # number of mallocs left + assert count2 == 0 # number of calls left + +def check(fn, signature, args, expected_result, must_be_removed=True): + remover = LLTypeMallocRemover() + t = TranslationContext() + t.buildannotator().build_types(fn, signature) + t.buildrtyper().specialize() + graph = graphof(t, fn) + if option.view: + t.view() + # to detect missing keepalives and broken intermediate graphs, + # we do the loop ourselves instead of calling remove_simple_mallocs() + while True: + progress = remover.remove_mallocs_once(graph) + simplify.transform_dead_op_vars_in_blocks(list(graph.iterblocks())) + if progress and option.view: + t.view() + if expected_result is not Ellipsis: + interp = LLInterpreter(t.rtyper) + res = interp.eval_graph(graph, args) + assert res == expected_result + if not progress: + break + if must_be_removed: + check_malloc_removed(graph) + return graph + + +def test_fn1(): + def fn1(x, y): + if x > 0: + t = x+y, x-y + else: + t = x-y, x+y + s, d = t + return s*d + check(fn1, [int, int], [15, 10], 125) + +def test_fn2(): + class T: + pass + def fn2(x, y): + t = T() + t.x = x + t.y = y + if x > 0: + return t.x + t.y + else: + return t.x - t.y + check(fn2, [int, int], [-6, 7], -13) + +def test_fn3(): + def fn3(x): + a, ((b, c), d, e) = x+1, ((x+2, x+3), x+4, x+5) + return a+b+c+d+e + check(fn3, [int], [10], 65) + +def test_fn4(): + class A: + pass + class B(A): + pass + def fn4(i): + a = A() + b = B() + a.b = b + b.i = i + return a.b.i + check(fn4, [int], [42], 42) + +def test_fn5(): + class A: + attr = 666 + class B(A): + attr = 42 + def fn5(): + b = B() + return b.attr + check(fn5, [], [], 42) + +def test_aliasing(): + class A: + pass + def fn6(n): + a1 = A() + a1.x = 5 + a2 = A() + a2.x = 6 + if n > 0: + a = a1 + else: + a = a2 + a.x = 12 + return a1.x + check(fn6, [int], [1], 12, must_be_removed=False) + +def test_with_keepalive(): + from pypy.rlib.objectmodel import keepalive_until_here + def fn1(x, y): + if x > 0: + t = x+y, x-y + else: + t = x-y, x+y + s, d = t + keepalive_until_here(t) + return s*d + check(fn1, [int, int], [15, 10], 125) + +def test_dont_remove_with__del__(): + import os + delcalls = [0] + class A(object): + nextid = 0 + def __init__(self): + self.id = self.nextid + self.nextid += 1 + + def __del__(self): + delcalls[0] += 1 + os.write(1, "__del__\n") + + def f(x=int): + a = A() + i = 0 + while i < x: a = A() - a.big = big - a.small = big.s - a.small.x = 0 - while i > 0: - a.small.x += i - i -= 1 - return a.small.x - self.check(fn7, [int], [10], 55, must_be_removed=False) - - def test_getsubstruct(self): - SMALL = lltype.Struct('SMALL', ('x', lltype.Signed)) - BIG = lltype.GcStruct('BIG', ('z', lltype.Signed), ('s', SMALL)) - - def fn(n1, n2): - b = lltype.malloc(BIG) - b.z = n1 - b.s.x = n2 - return b.z - b.s.x - - self.check(fn, [int, int], [100, 58], 42) - - def test_fixedsizearray(self): - A = lltype.FixedSizeArray(lltype.Signed, 3) - S = lltype.GcStruct('S', ('a', A)) - - def fn(n1, n2): - s = lltype.malloc(S) - a = s.a - a[0] = n1 - a[2] = n2 - return a[0]-a[2] - - self.check(fn, [int, int], [100, 42], 58) - - def test_wrapper_cannot_be_removed(self): - SMALL = lltype.OpaqueType('SMALL') - BIG = lltype.GcStruct('BIG', ('z', lltype.Signed), ('s', SMALL)) - - def g(small): - return -1 - def fn(): - b = lltype.malloc(BIG) - g(b.s) - - self.check(fn, [], [], None, must_be_removed=False) - - def test_direct_fieldptr(self): - S = lltype.GcStruct('S', ('x', lltype.Signed)) - - def fn(): - s = lltype.malloc(S) - s.x = 11 - p = lltype.direct_fieldptr(s, 'x') - return p[0] - - self.check(fn, [], [], 11) - - def test_direct_fieldptr_2(self): - T = lltype.GcStruct('T', ('z', lltype.Signed)) - S = lltype.GcStruct('S', ('t', T), - ('x', lltype.Signed), - ('y', lltype.Signed)) - def fn(): - s = lltype.malloc(S) - s.x = 10 - s.t.z = 1 - px = lltype.direct_fieldptr(s, 'x') - py = lltype.direct_fieldptr(s, 'y') - pz = lltype.direct_fieldptr(s.t, 'z') - py[0] = 31 - return px[0] + s.y + pz[0] - - self.check(fn, [], [], 42) - - def test_getarraysubstruct(self): - U = lltype.Struct('U', ('n', lltype.Signed)) - for length in [1, 2]: - S = lltype.GcStruct('S', ('a', lltype.FixedSizeArray(U, length))) - for index in range(length): - - def fn(): - s = lltype.malloc(S) - s.a[index].n = 12 - return s.a[index].n - self.check(fn, [], [], 12) - - def test_ptr_nonzero(self): - S = lltype.GcStruct('S') - def fn(): - s = lltype.malloc(S) - return bool(s) - self.check(fn, [], [], True) - - def test_substruct_not_accessed(self): - SMALL = lltype.Struct('SMALL', ('x', lltype.Signed)) - BIG = lltype.GcStruct('BIG', ('z', lltype.Signed), ('s', SMALL)) - def fn(): - x = lltype.malloc(BIG) - while x.z < 10: # makes several blocks - x.z += 3 - return x.z - self.check(fn, [], [], 12) - - def test_union(self): - UNION = lltype.Struct('UNION', ('a', lltype.Signed), ('b', lltype.Signed), - hints = {'union': True}) - BIG = lltype.GcStruct('BIG', ('u1', UNION), ('u2', UNION)) - def fn(): - x = lltype.malloc(BIG) - x.u1.a = 3 - x.u2.b = 6 - return x.u1.b * x.u2.a - self.check(fn, [], [], Ellipsis) - - def test_keep_all_keepalives(self): - SIZE = llmemory.sizeof(lltype.Signed) - PARRAY = lltype.Ptr(lltype.FixedSizeArray(lltype.Signed, 1)) - class A: - def __init__(self): - self.addr = llmemory.raw_malloc(SIZE) - def __del__(self): - llmemory.raw_free(self.addr) - class B: - pass - def myfunc(): - b = B() - b.keep = A() - b.data = llmemory.cast_adr_to_ptr(b.keep.addr, PARRAY) - b.data[0] = 42 - ptr = b.data - # normally 'b' could go away as early as here, which would free - # the memory held by the instance of A in b.keep... - res = ptr[0] - # ...so we explicitly keep 'b' alive until here - objectmodel.keepalive_until_here(b) - return res - graph = self.check(myfunc, [], [], 42, - must_be_removed=False) # 'A' instance left - - # there is a getarrayitem near the end of the graph of myfunc. - # However, the memory it accesses must still be protected by the - # following keepalive, even after malloc removal - entrymap = mkentrymap(graph) - [link] = entrymap[graph.returnblock] - assert link.prevblock.operations[-1].opname == 'keepalive' - -class TestOOTypeMallocRemoval(BaseMallocRemovalTest): - type_system = 'ootype' - MallocRemover = OOTypeMallocRemover - - def test_oononnull(self): - FOO = ootype.Instance('Foo', ootype.ROOT) - def fn(): - s = ootype.new(FOO) - return bool(s) - self.check(fn, [], [], True) + os.write(1, str(delcalls[0]) + "\n") + i += 1 + return 1 + t = TranslationContext() + t.buildannotator().build_types(f, [int]) + t.buildrtyper().specialize() + graph = graphof(t, f) + backend_optimizations(t) + op = graph.startblock.exits[0].target.exits[1].target.operations[0] + assert op.opname == "malloc" + +def test_add_keepalives(): + class A: + pass + SMALL = lltype.Struct('SMALL', ('x', lltype.Signed)) + BIG = lltype.GcStruct('BIG', ('z', lltype.Signed), ('s', SMALL)) + def fn7(i): + big = lltype.malloc(BIG) + a = A() + a.big = big + a.small = big.s + a.small.x = 0 + while i > 0: + a.small.x += i + i -= 1 + return a.small.x + check(fn7, [int], [10], 55, must_be_removed=False) + +def test_getsubstruct(): + SMALL = lltype.Struct('SMALL', ('x', lltype.Signed)) + BIG = lltype.GcStruct('BIG', ('z', lltype.Signed), ('s', SMALL)) + + def fn(n1, n2): + b = lltype.malloc(BIG) + b.z = n1 + b.s.x = n2 + return b.z - b.s.x + + check(fn, [int, int], [100, 58], 42) + +def test_fixedsizearray(): + A = lltype.FixedSizeArray(lltype.Signed, 3) + S = lltype.GcStruct('S', ('a', A)) + + def fn(n1, n2): + s = lltype.malloc(S) + a = s.a + a[0] = n1 + a[2] = n2 + return a[0]-a[2] + + check(fn, [int, int], [100, 42], 58) + +def test_wrapper_cannot_be_removed(): + SMALL = lltype.OpaqueType('SMALL') + BIG = lltype.GcStruct('BIG', ('z', lltype.Signed), ('s', SMALL)) + + def g(small): + return -1 + def fn(): + b = lltype.malloc(BIG) + g(b.s) + + check(fn, [], [], None, must_be_removed=False) + +def test_direct_fieldptr(): + S = lltype.GcStruct('S', ('x', lltype.Signed)) + + def fn(): + s = lltype.malloc(S) + s.x = 11 + p = lltype.direct_fieldptr(s, 'x') + return p[0] + + check(fn, [], [], 11) + +def test_direct_fieldptr_2(): + T = lltype.GcStruct('T', ('z', lltype.Signed)) + S = lltype.GcStruct('S', ('t', T), + ('x', lltype.Signed), + ('y', lltype.Signed)) + def fn(): + s = lltype.malloc(S) + s.x = 10 + s.t.z = 1 + px = lltype.direct_fieldptr(s, 'x') + py = lltype.direct_fieldptr(s, 'y') + pz = lltype.direct_fieldptr(s.t, 'z') + py[0] = 31 + return px[0] + s.y + pz[0] + + check(fn, [], [], 42) + +def test_getarraysubstruct(): + U = lltype.Struct('U', ('n', lltype.Signed)) + for length in [1, 2]: + S = lltype.GcStruct('S', ('a', lltype.FixedSizeArray(U, length))) + for index in range(length): + + def fn(): + s = lltype.malloc(S) + s.a[index].n = 12 + return s.a[index].n + check(fn, [], [], 12) + +def test_ptr_nonzero(): + S = lltype.GcStruct('S') + def fn(): + s = lltype.malloc(S) + return bool(s) + check(fn, [], [], True) + +def test_substruct_not_accessed(): + SMALL = lltype.Struct('SMALL', ('x', lltype.Signed)) + BIG = lltype.GcStruct('BIG', ('z', lltype.Signed), ('s', SMALL)) + def fn(): + x = lltype.malloc(BIG) + while x.z < 10: # makes several blocks + x.z += 3 + return x.z + check(fn, [], [], 12) + +def test_union(): + UNION = lltype.Struct('UNION', ('a', lltype.Signed), ('b', lltype.Signed), + hints = {'union': True}) + BIG = lltype.GcStruct('BIG', ('u1', UNION), ('u2', UNION)) + def fn(): + x = lltype.malloc(BIG) + x.u1.a = 3 + x.u2.b = 6 + return x.u1.b * x.u2.a + check(fn, [], [], Ellipsis) + +def test_keep_all_keepalives(): + SIZE = llmemory.sizeof(lltype.Signed) + PARRAY = lltype.Ptr(lltype.FixedSizeArray(lltype.Signed, 1)) + class A: + def __init__(self): + self.addr = llmemory.raw_malloc(SIZE) + def __del__(self): + llmemory.raw_free(self.addr) + class B: + pass + def myfunc(): + b = B() + b.keep = A() + b.data = llmemory.cast_adr_to_ptr(b.keep.addr, PARRAY) + b.data[0] = 42 + ptr = b.data + # normally 'b' could go away as early as here, which would free + # the memory held by the instance of A in b.keep... + res = ptr[0] + # ...so we explicitly keep 'b' alive until here + objectmodel.keepalive_until_here(b) + return res + graph = check(myfunc, [], [], 42, + must_be_removed=False) # 'A' instance left + + # there is a getarrayitem near the end of the graph of myfunc. + # However, the memory it accesses must still be protected by the + # following keepalive, even after malloc removal + entrymap = mkentrymap(graph) + [link] = entrymap[graph.returnblock] + assert link.prevblock.operations[-1].opname == 'keepalive' From pedronis at codespeak.net Sun Dec 31 02:12:37 2006 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Sun, 31 Dec 2006 02:12:37 +0100 (CET) Subject: [pypy-svn] r36069 - pypy/dist/pypy/translator Message-ID: <20061231011237.162DF10081@code0.codespeak.net> Author: pedronis Date: Sun Dec 31 02:12:34 2006 New Revision: 36069 Modified: pypy/dist/pypy/translator/driver.py Log: oops, missing in the last check-in. Modified: pypy/dist/pypy/translator/driver.py ============================================================================== --- pypy/dist/pypy/translator/driver.py (original) +++ pypy/dist/pypy/translator/driver.py Sun Dec 31 02:12:34 2006 @@ -357,7 +357,6 @@ if self.config.translation.backend == 'cli': opt['merge_if_blocks'] = True opt['inline_threshold'] = 1 - opt['mallocs'] = True backend_optimizations(self.translator, **opt) # task_backendopt_ootype = taskdef(task_backendopt_ootype, From arigo at codespeak.net Sun Dec 31 13:24:32 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 31 Dec 2006 13:24:32 +0100 (CET) Subject: [pypy-svn] r36072 - pypy/dist/pypy/translator/llvm/pyllvm/test Message-ID: <20061231122432.14A7710081@code0.codespeak.net> Author: arigo Date: Sun Dec 31 13:24:22 2006 New Revision: 36072 Modified: pypy/dist/pypy/translator/llvm/pyllvm/test/test_ee.py Log: Skip the pyllvm test. Should be removed at some point. The modern way to do this is jit/codegen/llvm. Modified: pypy/dist/pypy/translator/llvm/pyllvm/test/test_ee.py ============================================================================== --- pypy/dist/pypy/translator/llvm/pyllvm/test/test_ee.py (original) +++ pypy/dist/pypy/translator/llvm/pyllvm/test/test_ee.py Sun Dec 31 13:24:22 2006 @@ -2,7 +2,7 @@ from pypy.translator.llvm.buildllvm import llvm_is_on_path #if not llvm_is_on_path(): # py.test.skip("llvm not found") -#py.test.skip('aborts with SIGIOT on the snake machine :-(') +py.test.skip('not useful to keep around, will be removed soon') try: from pypy.translator.llvm.pyllvm import pyllvm From arigo at codespeak.net Sun Dec 31 14:16:01 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 31 Dec 2006 14:16:01 +0100 (CET) Subject: [pypy-svn] r36073 - in pypy/dist/pypy/rlib/rctypes: . test Message-ID: <20061231131601.6092E10081@code0.codespeak.net> Author: arigo Date: Sun Dec 31 14:15:58 2006 New Revision: 36073 Modified: pypy/dist/pypy/rlib/rctypes/rctypesobject.py pypy/dist/pypy/rlib/rctypes/test/test_rctypesobject.py Log: rctypesobject: support for NULL pointers. Modified: pypy/dist/pypy/rlib/rctypes/rctypesobject.py ============================================================================== --- pypy/dist/pypy/rlib/rctypes/rctypesobject.py (original) +++ pypy/dist/pypy/rlib/rctypes/rctypesobject.py Sun Dec 31 14:15:58 2006 @@ -267,6 +267,18 @@ keepalive_until_here(self) self._keepalivememblock(0, targetmemblock) + def is_null(self): + ptr = self.ll_ref(RCTypesPtr.CDATATYPE) + res = not ptr[0] + keepalive_until_here(self) + return res + + def set_null(self): + ptr = self.ll_ref(RCTypesPtr.CDATATYPE) + ptr[0] = lltype.nullptr(RCTypesPtr.LLTYPE.TO) + keepalive_until_here(self) + self._keepalivememblock(0, None) + ofs_item = llmemory.sizeof(contentscls.LLTYPE) contentscls._ptrcls = RCTypesPtr return RCTypesPtr Modified: pypy/dist/pypy/rlib/rctypes/test/test_rctypesobject.py ============================================================================== --- pypy/dist/pypy/rlib/rctypes/test/test_rctypesobject.py (original) +++ pypy/dist/pypy/rlib/rctypes/test/test_rctypesobject.py Sun Dec 31 14:15:58 2006 @@ -240,6 +240,20 @@ res = self.do(func) assert res == 115 + 206 + def test_null_pointer(self): + P = RPointer(rc_int) + def func(): + x = rc_int.allocate() + p = P.allocate() + res1 = p.is_null() + p.set_contents(x) + res2 = p.is_null() + p.set_null() + res3 = p.is_null() + return res1 * 100 + res2 * 10 + res3 + res = self.do(func) + assert res == 101 + POLICY = AnnotatorPolicy() POLICY.allow_someobjects = False From arigo at codespeak.net Sun Dec 31 14:46:11 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 31 Dec 2006 14:46:11 +0100 (CET) Subject: [pypy-svn] r36074 - in pypy/dist/pypy/rlib/rctypes: . test Message-ID: <20061231134611.0E25A10081@code0.codespeak.net> Author: arigo Date: Sun Dec 31 14:45:54 2006 New Revision: 36074 Modified: pypy/dist/pypy/rlib/rctypes/rctypesobject.py pypy/dist/pypy/rlib/rctypes/test/test_rctypesobject.py Log: Rename the pointers' get_contents_at_index() to ref() to be the same method name as arrays. Modified: pypy/dist/pypy/rlib/rctypes/rctypesobject.py ============================================================================== --- pypy/dist/pypy/rlib/rctypes/rctypesobject.py (original) +++ pypy/dist/pypy/rlib/rctypes/rctypesobject.py Sun Dec 31 14:45:54 2006 @@ -249,10 +249,11 @@ targetmemblock = self._getmemblock(0, targetkeepalives) return contentscls(targetaddr, targetmemblock) - def get_contents_at_index(self, index): + def ref(self, index): ptr = self.ll_ref(RCTypesPtr.CDATATYPE) targetaddr = llmemory.cast_ptr_to_adr(ptr[0]) - targetaddr += ofs_item * index + if index: + targetaddr += ofs_item * index keepalive_until_here(self) targetkeepalives = contentscls.num_keepalives targetmemblock = self._getmemblock(0, targetkeepalives) Modified: pypy/dist/pypy/rlib/rctypes/test/test_rctypesobject.py ============================================================================== --- pypy/dist/pypy/rlib/rctypes/test/test_rctypesobject.py (original) +++ pypy/dist/pypy/rlib/rctypes/test/test_rctypesobject.py Sun Dec 31 14:45:54 2006 @@ -221,7 +221,7 @@ a.ref(i).set_value(100 + 5 * i) p = pointer(a.ref(0)) del a - return p.get_contents_at_index(7).get_value() + return p.ref(7).get_value() res = self.do(func) assert res == 135 @@ -235,7 +235,7 @@ a.ref(i).ref_y().set_value(200 + 2 * i) p = pointer(a.ref(0)) del a - s1 = p.get_contents_at_index(3) + s1 = p.ref(3) return s1.ref_x().get_value() + s1.ref_y().get_value() res = self.do(func) assert res == 115 + 206 From arigo at codespeak.net Sun Dec 31 14:48:37 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 31 Dec 2006 14:48:37 +0100 (CET) Subject: [pypy-svn] r36075 - in pypy/dist/pypy: rlib/rctypes rlib/rctypes/test rpython Message-ID: <20061231134837.11D0510081@code0.codespeak.net> Author: arigo Date: Sun Dec 31 14:48:34 2006 New Revision: 36075 Modified: pypy/dist/pypy/rlib/rctypes/implementation.py pypy/dist/pypy/rlib/rctypes/rarray.py pypy/dist/pypy/rlib/rctypes/rpointer.py pypy/dist/pypy/rlib/rctypes/rprimitive.py pypy/dist/pypy/rlib/rctypes/rstruct.py pypy/dist/pypy/rlib/rctypes/test/test_rpointer.py pypy/dist/pypy/rpython/controllerentry.py pypy/dist/pypy/rpython/rcontrollerentry.py Log: The pointer tests pass. Modified: pypy/dist/pypy/rlib/rctypes/implementation.py ============================================================================== --- pypy/dist/pypy/rlib/rctypes/implementation.py (original) +++ pypy/dist/pypy/rlib/rctypes/implementation.py Sun Dec 31 14:48:34 2006 @@ -55,6 +55,13 @@ return_value = Controller.box + def store_box(self, obj, valuebox): + obj.copyfrom(valuebox) + + def store_value(self, obj, value): + raise TypeError("cannot store a value into a non-primitive ctype") + store_value._annspecialcase_ = 'specialize:arg(0)' + # extension to the setattr/setitem support: if the new value is actually # a CTypeControlled instance as well, reveal it automatically (i.e. turn # it into an rctypesobject) and call a method with a different name. Modified: pypy/dist/pypy/rlib/rctypes/rarray.py ============================================================================== --- pypy/dist/pypy/rlib/rctypes/rarray.py (original) +++ pypy/dist/pypy/rlib/rctypes/rarray.py Sun Dec 31 14:48:34 2006 @@ -18,17 +18,17 @@ self.itemcontroller.knowntype, self.length) - def new(self, *args): - obj = self.knowntype.allocate() - if args: - if len(args) > self.length: - raise ValueError("too many arguments for an array of " - "length %d" % (self.length,)) - lst = list(args) - for i in range(len(args)): - self.setitem(obj, i, lst[i]) - return obj - new._annspecialcase_ = 'specialize:arg(0)' + def arraynew(*args): + obj = self.knowntype.allocate() + if args: + if len(args) > self.length: + raise ValueError("too many arguments for an array of " + "length %d" % (self.length,)) + lst = list(args) + for i in range(len(args)): + self.setitem(obj, i, lst[i]) + return obj + self.new = arraynew def getitem(self, obj, i): itemobj = obj.ref(i) Modified: pypy/dist/pypy/rlib/rctypes/rpointer.py ============================================================================== --- pypy/dist/pypy/rlib/rctypes/rpointer.py (original) +++ pypy/dist/pypy/rlib/rctypes/rpointer.py Sun Dec 31 14:48:34 2006 @@ -22,15 +22,14 @@ if ptrto is not None: obj.set_contents(self.contentscontroller.unbox(ptrto)) return obj + new._annspecialcase_ = 'specialize:arg(0)' def initialize_prebuilt(self, obj, x): contentsbox = self.contentscontroller.convert(x.contents) self.setbox_contents(obj, contentsbox) def getitem(self, obj, index): - if index != 0: - raise ValueError("can only access item 0 of pointers") - contentsobj = obj.get_contents() + contentsobj = obj.ref(index) return self.contentscontroller.return_value(contentsobj) getitem._annspecialcase_ = 'specialize:arg(0)' @@ -58,4 +57,11 @@ obj.set_contents(contentsbox) setbox_contents._annspecialcase_ = 'specialize:arg(0)' + def is_true(self, obj): + return not obj.is_null() + is_true._annspecialcase_ = 'specialize:arg(0)' + + def store_box(self, obj, valuebox): + obj.set_contents(valuebox.ref(0)) + PointerCTypeController.register_for_metatype(PointerType) Modified: pypy/dist/pypy/rlib/rctypes/rprimitive.py ============================================================================== --- pypy/dist/pypy/rlib/rctypes/rprimitive.py (original) +++ pypy/dist/pypy/rlib/rctypes/rprimitive.py Sun Dec 31 14:48:34 2006 @@ -40,14 +40,14 @@ self.is_char_type = self.VALUETYPE in (lltype.Char, lltype.UniChar) self.knowntype = rctypesobject.Primitive(self.VALUETYPE) - def new(self, *initialvalue): - obj = self.knowntype.allocate() - if len(initialvalue) > 0: - if len(initialvalue) > 1: - raise TypeError("at most 1 argument expected") - self.set_value(obj, initialvalue[0]) - return obj - new._annspecialcase_ = 'specialize:arg(0)' + def primitivenew(*initialvalue): + obj = self.knowntype.allocate() + if len(initialvalue) > 0: + if len(initialvalue) > 1: + raise TypeError("at most 1 argument expected") + self.set_value(obj, initialvalue[0]) + return obj + self.new = primitivenew def initialize_prebuilt(self, obj, x): value = x.value @@ -78,6 +78,7 @@ # ctypes automatically unwraps the c_xxx() of primitive types when # they are returned by most operations return_value = get_value + store_value = set_value def is_true(self, obj): llvalue = self.get_value(obj) Modified: pypy/dist/pypy/rlib/rctypes/rstruct.py ============================================================================== --- pypy/dist/pypy/rlib/rctypes/rstruct.py (original) +++ pypy/dist/pypy/rlib/rctypes/rstruct.py Sun Dec 31 14:48:34 2006 @@ -37,8 +37,10 @@ if args: value = args[0] args = args[1:] - itemobj = getattr(obj, 'ref_' + name)() - controller.set_value(itemobj, value) + if controller.is_box(value): + structsetboxattr(obj, name, value) + else: + structsetattr(obj, name, value) return obj self.new = structnew @@ -53,11 +55,18 @@ def structsetattr(obj, attr, value): controller = getattr(self, 'fieldcontroller_' + attr) itemobj = getattr(obj, 'ref_' + attr)() - controller.set_value(itemobj, value) + controller.store_value(itemobj, value) structsetattr._annspecialcase_ = 'specialize:arg(1)' + def structsetboxattr(obj, attr, valuebox): + controller = getattr(self, 'fieldcontroller_' + attr) + itemobj = getattr(obj, 'ref_' + attr)() + controller.store_box(itemobj, valuebox) + structsetboxattr._annspecialcase_ = 'specialize:arg(1)' + self.getattr = structgetattr self.setattr = structsetattr + self.setboxattr = structsetboxattr StructCTypeController.register_for_metatype(StructType) Modified: pypy/dist/pypy/rlib/rctypes/test/test_rpointer.py ============================================================================== --- pypy/dist/pypy/rlib/rctypes/test/test_rpointer.py (original) +++ pypy/dist/pypy/rlib/rctypes/test/test_rpointer.py Sun Dec 31 14:48:34 2006 @@ -104,7 +104,7 @@ ## assert not s.ownsmemory -class INPROGRESS_Test_specialization: +class Test_specialization: def test_specialize_c_int_ptr(self): ptrtype = POINTER(c_int) def func(): @@ -221,11 +221,10 @@ def fn(): p = POINTER(c_double)() p.contents = c_double(6.25) - return p + return p.contents.value res = interpret(fn, []) - float_c_data = res.c_data[0] - assert float_c_data[0] == 6.25 + assert res == 6.25 def test_specialize_getitem_nonzero_index(self): A = c_int * 10 Modified: pypy/dist/pypy/rpython/controllerentry.py ============================================================================== --- pypy/dist/pypy/rpython/controllerentry.py (original) +++ pypy/dist/pypy/rpython/controllerentry.py Sun Dec 31 14:48:34 2006 @@ -24,6 +24,17 @@ return controller.rtype_new(hop) + +def controlled_instance_box(controller, obj): + XXX # only for special-casing by ExtRegistryEntry below + +def controlled_instance_unbox(controller, obj): + XXX # only for special-casing by ExtRegistryEntry below + +def controlled_instance_is_box(controller, obj): + XXX # only for special-casing by ExtRegistryEntry below + + class ControllerEntryForPrebuilt(ExtRegistryEntry): def compute_annotation(self): @@ -50,6 +61,10 @@ return controlled_instance_unbox(self, obj) unbox._annspecialcase_ = 'specialize:arg(0)' + def is_box(self, obj): + return controlled_instance_is_box(self, obj) + is_box._annspecialcase_ = 'specialize:arg(0)' + def ctrl_new(self, *args_s): s_real_obj = delegate(self.new, *args_s) if s_real_obj == annmodel.s_ImpossibleValue: @@ -111,12 +126,6 @@ return bk.emulate_pbc_call(bk.position_key, s_meth, args_s, callback = bk.position_key) -def controlled_instance_box(controller, obj): - XXX - -def controlled_instance_unbox(controller, obj): - XXX - class BoxEntry(ExtRegistryEntry): _about_ = controlled_instance_box @@ -129,8 +138,12 @@ return SomeControlledInstance(s_real_obj, controller=controller) def specialize_call(self, hop): - [v] = hop.inputargs(hop.r_result) - return v + from pypy.rpython.rcontrollerentry import ControlledInstanceRepr + if not isinstance(hop.r_result, ControlledInstanceRepr): + raise TyperError("box() should return ControlledInstanceRepr,\n" + "got %r" % (hop.r_result,)) + hop.exception_cannot_occur() + return hop.inputarg(hop.r_result.r_real_obj, arg=1) class UnboxEntry(ExtRegistryEntry): _about_ = controlled_instance_unbox @@ -143,8 +156,31 @@ return s_obj.s_real_obj def specialize_call(self, hop): - [v] = hop.inputargs(hop.r_result) - return v + from pypy.rpython.rcontrollerentry import ControlledInstanceRepr + if not isinstance(hop.args_r[1], ControlledInstanceRepr): + raise TyperError("unbox() should take a ControlledInstanceRepr,\n" + "got %r" % (hop.args_r[1],)) + hop.exception_cannot_occur() + v = hop.inputarg(hop.args_r[1], arg=1) + return hop.llops.convertvar(v, hop.args_r[1].r_real_obj, hop.r_result) + +class IsBoxEntry(ExtRegistryEntry): + _about_ = controlled_instance_is_box + + def compute_result_annotation(self, s_controller, s_obj): + if s_obj == annmodel.s_ImpossibleValue: + return annmodel.s_ImpossibleValue + else: + assert s_controller.is_constant() + controller = s_controller.const + result = (isinstance(s_obj, SomeControlledInstance) and + s_obj.controller == controller) + return self.bookkeeper.immutablevalue(result) + + def specialize_call(self, hop): + from pypy.rpython.lltypesystem import lltype + assert hop.s_result.is_constant() + return hop.inputconst(lltype.Bool, hop.s_result.const) # ____________________________________________________________ Modified: pypy/dist/pypy/rpython/rcontrollerentry.py ============================================================================== --- pypy/dist/pypy/rpython/rcontrollerentry.py (original) +++ pypy/dist/pypy/rpython/rcontrollerentry.py Sun Dec 31 14:48:34 2006 @@ -17,6 +17,11 @@ real_value = self.controller.convert(value) return self.r_real_obj.convert_const(real_value) + def reveal(self, r): + if r is not self: + raise TyperError("expected %r, got %r" % (self, r)) + return self.s_real_obj, self.r_real_obj + def rtype_getattr(self, hop): return self.controller.rtype_getattr(hop) From arigo at codespeak.net Sun Dec 31 14:53:26 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 31 Dec 2006 14:53:26 +0100 (CET) Subject: [pypy-svn] r36076 - pypy/dist/pypy/rlib/rctypes/test Message-ID: <20061231135326.7C28B10081@code0.codespeak.net> Author: arigo Date: Sun Dec 31 14:53:23 2006 New Revision: 36076 Modified: pypy/dist/pypy/rlib/rctypes/test/test_rpointer.py Log: Last test passes too. Modified: pypy/dist/pypy/rlib/rctypes/test/test_rpointer.py ============================================================================== --- pypy/dist/pypy/rlib/rctypes/test/test_rpointer.py (original) +++ pypy/dist/pypy/rlib/rctypes/test/test_rpointer.py Sun Dec 31 14:53:23 2006 @@ -263,7 +263,7 @@ res = interpret(fn, [-12]) assert res == 55 -class INPROGRESS_Test_compilation: +class Test_compilation: def test_compile_getitem_nonzero_index(self): A = c_int * 10 class S(Structure): From fijal at codespeak.net Sun Dec 31 16:03:13 2006 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 31 Dec 2006 16:03:13 +0100 (CET) Subject: [pypy-svn] r36077 - in pypy/dist/pypy: doc/js translator/js/doc Message-ID: <20061231150313.5DF7C10071@code0.codespeak.net> Author: fijal Date: Sun Dec 31 16:03:10 2006 New Revision: 36077 Added: pypy/dist/pypy/doc/js/webapps_with_pypy.txt - copied unchanged from r36076, pypy/dist/pypy/translator/js/doc/webapps_with_pypy.txt Removed: pypy/dist/pypy/translator/js/doc/webapps_with_pypy.txt Log: Moved document to proper dir. From cfbolz at codespeak.net Sun Dec 31 17:27:44 2006 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Sun, 31 Dec 2006 17:27:44 +0100 (CET) Subject: [pypy-svn] r36079 - pypy/dist/pypy/objspace/std/test Message-ID: <20061231162744.D5AED10082@code0.codespeak.net> Author: cfbolz Date: Sun Dec 31 17:27:44 2006 New Revision: 36079 Modified: pypy/dist/pypy/objspace/std/test/test_dictmultiobject.py Log: rename test classes to actually test everything :-( Modified: pypy/dist/pypy/objspace/std/test/test_dictmultiobject.py ============================================================================== --- pypy/dist/pypy/objspace/std/test/test_dictmultiobject.py (original) +++ pypy/dist/pypy/objspace/std/test/test_dictmultiobject.py Sun Dec 31 17:27:44 2006 @@ -6,24 +6,23 @@ from pypy.conftest import gettestobjspace from pypy.objspace.std.test import test_dictobject -class TestW_DictObject(test_dictobject.TestW_DictObject): +class TestW_DictMultiObject(test_dictobject.TestW_DictObject): def setup_class(cls): cls.space = gettestobjspace(**{"objspace.std.withmultidict": True}) -class AppTest_DictObject(test_dictobject.AppTest_DictObject): +class AppTest_DictMultiObject(test_dictobject.AppTest_DictObject): def setup_class(cls): cls.space = gettestobjspace(**{"objspace.std.withmultidict": True}) -class TestW_DictObject(test_dictobject.TestW_DictObject): +class TestW_DictSharing(test_dictobject.TestW_DictObject): def setup_class(cls): cls.space = gettestobjspace(**{"objspace.std.withsharingdict": True}) -class AppTest_DictObject(test_dictobject.AppTest_DictObject): +class AppTest_DictSharing(test_dictobject.AppTest_DictObject): def setup_class(cls): cls.space = gettestobjspace(**{"objspace.std.withsharingdict": True}) - class FakeSpace(test_dictobject.FakeSpace): def str_w(self, string): assert isinstance(string, str) From cfbolz at codespeak.net Sun Dec 31 17:31:33 2006 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Sun, 31 Dec 2006 17:31:33 +0100 (CET) Subject: [pypy-svn] r36080 - in pypy/dist/pypy/objspace/std: . test Message-ID: <20061231163133.92A9310088@code0.codespeak.net> Author: cfbolz Date: Sun Dec 31 17:31:33 2006 New Revision: 36080 Modified: pypy/dist/pypy/objspace/std/dictmultiobject.py pypy/dist/pypy/objspace/std/test/test_dictmultiobject.py Log: test + bug fix: the result of .__dict__.values could be mutated to change when using sharing dicts. Modified: pypy/dist/pypy/objspace/std/dictmultiobject.py ============================================================================== --- pypy/dist/pypy/objspace/std/dictmultiobject.py (original) +++ pypy/dist/pypy/objspace/std/dictmultiobject.py Sun Dec 31 17:31:33 2006 @@ -574,7 +574,7 @@ if item >= 0] def values(self): - return self.entries + return self.entries[:] def items(self): space = self.space Modified: pypy/dist/pypy/objspace/std/test/test_dictmultiobject.py ============================================================================== --- pypy/dist/pypy/objspace/std/test/test_dictmultiobject.py (original) +++ pypy/dist/pypy/objspace/std/test/test_dictmultiobject.py Sun Dec 31 17:31:33 2006 @@ -22,6 +22,16 @@ def setup_class(cls): cls.space = gettestobjspace(**{"objspace.std.withsharingdict": True}) + def test_values_does_not_share(self): + class A(object): + pass + a = A() + a.abc = 12 + l = a.__dict__.values() + assert l == [12] + l[0] = 24 + assert a.abc == 12 + class FakeSpace(test_dictobject.FakeSpace): def str_w(self, string):